diff --git a/Controllers/RecruitController.cs b/Controllers/RecruitController.cs index 5ea2895..a32cee5 100644 --- a/Controllers/RecruitController.cs +++ b/Controllers/RecruitController.cs @@ -1104,19 +1104,18 @@ namespace BMA.EHR.Recruit.Service.Controllers r.LastName = workSheet?.Cells[row, 8]?.GetValue() ?? ""; r.Gendor = workSheet?.Cells[row, 98]?.GetValue() ?? ""; r.National = workSheet?.Cells[row, 9]?.GetValue() ?? ""; - r.Race = workSheet?.Cells[row, 9999]?.GetValue() ?? ""; + r.Race = ""; r.Religion = workSheet?.Cells[row, 10]?.GetValue() ?? ""; - r.DateOfBirth = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 11]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 11]?.GetValue() ?? "", "dd/MM/yyyy") : DateTime.MinValue; + r.DateOfBirth = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 11]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 11]?.GetValue() ?? "", "dd/MM/yyyy") : null; r.CitizenId = workSheet?.Cells[row, 12]?.GetValue() ?? ""; r.typeTest = workSheet?.Cells[row, 13]?.GetValue() ?? ""; - r.Marry = workSheet?.Cells[row, 9999]?.GetValue() ?? ""; + r.Marry = ""; r.Isspecial = "N"; - r.CitizenCardIssuer = workSheet?.Cells[row, 9999]?.GetValue() ?? ""; - r.CitizenCardExpireDate = Convert.ToDateTime(workSheet?.Cells[row, 9999]?.GetValue().ToDateTime(DateTimeFormat.Ymd, "-")); - r.ApplyDate = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 87]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 87]?.GetValue() ?? "", "dd/MM/yyyy") : DateTime.MinValue; - r.PositionType = workSheet?.Cells[row, 9999]?.GetValue() ?? ""; - r.PositionLevel = workSheet?.Cells[row, 9999]?.GetValue() ?? ""; - + r.CitizenCardExpireDate = null; + r.ModifiedDate = null; + r.ApplyDate = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 87]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 87]?.GetValue() ?? "", "dd/MM/yyyy") : null; + r.PositionType = ""; + r.PositionLevel = ""; r.CreatedAt = DateTime.Now; r.CreatedUserId = UserId ?? ""; r.CreatedFullName = FullName ?? "System Administrator"; @@ -1129,13 +1128,13 @@ namespace BMA.EHR.Recruit.Service.Controllers { Degree = workSheet?.Cells[row, 18]?.GetValue() ?? "", Major = workSheet?.Cells[row, 19]?.GetValue() == "อื่น ๆ" ? workSheet?.Cells[row, 20]?.GetValue() ?? "" : workSheet?.Cells[row, 19]?.GetValue() ?? "", - MajorGroupId = workSheet?.Cells[row, 9999]?.GetValue() ?? "", - MajorGroupName = workSheet?.Cells[row, 9999]?.GetValue() ?? "", + MajorGroupId = "", + MajorGroupName = "", University = workSheet?.Cells[row, 21]?.GetValue() == "อื่น ๆ" ? workSheet?.Cells[row, 22]?.GetValue() ?? "" : workSheet?.Cells[row, 21]?.GetValue() ?? "", GPA = (double)workSheet?.Cells[row, 26]?.GetValue(), - Specialist = workSheet?.Cells[row, 9999]?.GetValue() ?? "", + Specialist = "", HighDegree = workSheet?.Cells[row, 27]?.GetValue() ?? "", - BachelorDate = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 25]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 11]?.GetValue() ?? "", "dd/MM/yyyy") : DateTime.MinValue, + BachelorDate = !string.IsNullOrWhiteSpace(workSheet?.Cells[row, 25]?.GetValue()) ? _recruitService.CheckDateTime(workSheet?.Cells[row, 25]?.GetValue() ?? "", "dd/MM/yyyy") : null, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", CreatedFullName = FullName ?? "System Administrator", @@ -1172,7 +1171,7 @@ namespace BMA.EHR.Recruit.Service.Controllers Province = workSheet?.Cells[row, 56]?.GetValue() ?? "", ZipCode = workSheet?.Cells[row, 57]?.GetValue() ?? "", Telephone = workSheet?.Cells[row, 58]?.GetValue() ?? "", - Mobile = workSheet?.Cells[row, 9999]?.GetValue() ?? "", + Mobile = "", Address1 = $"{(workSheet?.Cells[row, 61]?.GetValue() ?? "")} {(workSheet?.Cells[row, 62]?.GetValue() ?? "")}", Moo1 = workSheet?.Cells[row, 63]?.GetValue() ?? "", Soi1 = workSheet?.Cells[row, 64]?.GetValue() ?? "", @@ -1215,21 +1214,21 @@ namespace BMA.EHR.Recruit.Service.Controllers LastUpdateUserId = UserId ?? "", LastUpdateFullName = FullName ?? "System Administrator" }); - - // certificate - r.Certificates.Add(new RecruitCertificate() - { - CertificateNo = workSheet?.Cells[row, 9999]?.GetValue() ?? "", - Description = workSheet?.Cells[row, 9999]?.GetValue() ?? "", - IssueDate = Convert.ToDateTime(workSheet?.Cells[row, 9999]?.GetValue().ToDateTime(DateTimeFormat.Ymd, "-")), - ExpiredDate = Convert.ToDateTime(workSheet?.Cells[row, 9999]?.GetValue().ToDateTime(DateTimeFormat.Ymd, "-")), - CreatedAt = DateTime.Now, - CreatedUserId = UserId ?? "", - CreatedFullName = FullName ?? "System Administrator", - LastUpdatedAt = DateTime.Now, - LastUpdateUserId = UserId ?? "", - LastUpdateFullName = FullName ?? "System Administrator" - }); + /*Comment ข้อมูลใบประกอบวิชาชีพ เพราะในไฟล์นำเข้ายังไม่มีคอลัมน์ที่ระบุข้อมูลส่วนนี้*/ + //// certificate + //r.Certificates.Add(new RecruitCertificate() + //{ + // CertificateNo = workSheet?.Cells[row, 9999]?.GetValue() ?? "", + // Description = workSheet?.Cells[row, 9999]?.GetValue() ?? "", + // IssueDate = Convert.ToDateTime(workSheet?.Cells[row, 9999]?.GetValue().ToDateTime(DateTimeFormat.Ymd, "-")), + // ExpiredDate = Convert.ToDateTime(workSheet?.Cells[row, 9999]?.GetValue().ToDateTime(DateTimeFormat.Ymd, "-")), + // CreatedAt = DateTime.Now, + // CreatedUserId = UserId ?? "", + // CreatedFullName = FullName ?? "System Administrator", + // LastUpdatedAt = DateTime.Now, + // LastUpdateUserId = UserId ?? "", + // LastUpdateFullName = FullName ?? "System Administrator" + //}); r.RecruitImport = imported; _context.Recruits.Add(r); @@ -1980,13 +1979,8 @@ namespace BMA.EHR.Recruit.Service.Controllers ); } - int total = await query.CountAsync(); - - query = query - .Skip((req.Page - 1) * req.PageSize) - .Take(req.PageSize); - - var data = await query + // join กับ DisableScores ก่อน เพื่อ filter ตาม ExamStatus + var queryWithScores = query .GroupJoin( _context.RecruitScores.Include(x => x.ScoreImport), rc => new { rc.RecruitImport!.Id, rc.ExamId }, @@ -1995,49 +1989,78 @@ namespace BMA.EHR.Recruit.Service.Controllers ) .SelectMany( x => x.scores.DefaultIfEmpty(), - (x, sr) => new - { - examID = x.recruit.ExamId, - profileID = x.recruit.CitizenId, - prefix = x.recruit.Prefix, - fullName = $"{x.recruit.FirstName} {x.recruit.LastName}", - dateOfBirth = x.recruit.DateOfBirth != null && x.recruit.DateOfBirth != DateTime.MinValue - ? x.recruit.DateOfBirth.ToThaiShortDate() - : "", - gender = x.recruit.Gendor, - degree = x.recruit.Educations.Any() ? x.recruit.Educations.First().Degree : "", - major = x.recruit.Educations.Any() ? x.recruit.Educations.First().Major : "", - certificateNo = x.recruit.Certificates.Any() - ? x.recruit.Certificates.First().CertificateNo ?? "" - : "", - certificateIssueDate = x.recruit.Certificates.Any() && x.recruit.Certificates.First().IssueDate != null && x.recruit.Certificates.First().IssueDate != DateTime.MinValue - ? x.recruit.Certificates.First().IssueDate.ToThaiShortDate() - : "", - examScore = sr == null ? 0.0 : sr.TotalScore, - examResult = sr == null ? "" : sr.ExamStatus, - examAttribute = x.recruit.Certificates.Any() && x.recruit.Certificates.First().IssueDate != null - ? _recruitService.CheckValidCertificate(x.recruit.Certificates.First().IssueDate, 5) - ? "มีคุณสมบัติ" : "ไม่มีคุณสมบัติ" - : "ไม่มีคุณสมบัติ", - remark = x.recruit.Remark, - isSpecial = x.recruit.Isspecial == "Y" ? x.recruit.Isspecial : "", - applyDate = x.recruit.ApplyDate != null && x.recruit.ApplyDate != DateTime.MinValue - ? x.recruit.ApplyDate.ToThaiShortDate() - : "", - university = x.recruit.Educations.Any() ? x.recruit.Educations.First().University : "", - position_name = x.recruit.PositionName, - hddPosition = x.recruit.HddPosition, - typeTest = x.recruit.typeTest, - position_level = x.recruit.PositionLevel, - position_type = x.recruit.PositionType, - exam_name = x.recruit.RecruitImport!.Name, - exam_order = x.recruit.RecruitImport != null && x.recruit.RecruitImport.Order != null - ? x.recruit.RecruitImport.Order.ToString() - : "", - score_year = x.recruit.RecruitImport != null && x.recruit.RecruitImport.Year != null - ? x.recruit.RecruitImport.Year.ToThaiYear().ToString() - : "", - }) + (x, sr) => new { x.recruit, score = sr } + ); + + // filter ตาม req.ExamResult + if (!string.IsNullOrWhiteSpace(req.ExamResult)) + { + switch (req.ExamResult.ToLower()) + { + case "missed_exam": + queryWithScores = queryWithScores.Where(x => x.score != null && x.score.ExamStatus == "ขส."); + break; + case "pass": + queryWithScores = queryWithScores.Where(x => x.score != null && x.score.ExamStatus == "ผ่าน"); + break; + case "notpass": + queryWithScores = queryWithScores.Where(x => x.score != null && x.score.ExamStatus == "ไม่ผ่าน"); + break; + } + } + + // total count หลังกรอง + int total = await queryWithScores.CountAsync(); + + // pagination + queryWithScores = queryWithScores + .Skip((req.Page - 1) * req.PageSize) + .Take(req.PageSize); + + // mapping + var data = await queryWithScores + .Select(x => new + { + examID = x.recruit.ExamId, + profileID = x.recruit.CitizenId, + prefix = x.recruit.Prefix, + fullName = $"{x.recruit.FirstName} {x.recruit.LastName}", + dateOfBirth = x.recruit.DateOfBirth.HasValue && x.recruit.DateOfBirth.Value != DateTime.MinValue + ? x.recruit.DateOfBirth.Value.ToThaiShortDate() + : "", + gender = x.recruit.Gendor, + degree = x.recruit.Educations.Any() ? x.recruit.Educations.First().Degree : "", + major = x.recruit.Educations.Any() ? x.recruit.Educations.First().Major : "", + certificateNo = x.recruit.Certificates.Any() ? x.recruit.Certificates.First().CertificateNo ?? "" : "", + certificateIssueDate = x.recruit.Certificates.Any() && x.recruit.Certificates.First().IssueDate != null && x.recruit.Certificates.First().IssueDate != DateTime.MinValue + ? x.recruit.Certificates.First().IssueDate.ToThaiShortDate() + : "", + examScore = x.score == null ? 0.0 : x.score.TotalScore, + examResult = x.score == null ? "" : x.score.ExamStatus, + examAttribute = x.recruit.Certificates.Any() && x.recruit.Certificates.First().IssueDate != null + ? _recruitService.CheckValidCertificate(x.recruit.Certificates.First().IssueDate, 5) + ? "มีคุณสมบัติ" : "ไม่มีคุณสมบัติ" + : "ไม่มีคุณสมบัติ", + remark = x.recruit.Remark, + isSpecial = x.recruit.Isspecial == "Y" ? x.recruit.Isspecial : "", + applyDate = x.recruit.ApplyDate.HasValue && x.recruit.ApplyDate.Value != DateTime.MinValue + ? x.recruit.ApplyDate.Value.ToThaiShortDate() + : "", + university = x.recruit.Educations.Any() ? x.recruit.Educations.First().University : "", + position_name = x.recruit.PositionName, + hddPosition = x.recruit.HddPosition ?? "", + typeTest = x.recruit.typeTest ?? "", + position_level = x.recruit.PositionLevel ?? "", + position_type = x.recruit.PositionType ?? "", + exam_name = x.recruit.RecruitImport!.Name, + exam_order = x.recruit.RecruitImport != null && x.recruit.RecruitImport.Order != null + ? x.recruit.RecruitImport.Order.ToString() + : "", + score_year = x.recruit.RecruitImport != null && x.recruit.RecruitImport.Year != null + ? (x.recruit.RecruitImport.Year > 2500 ? x.recruit.RecruitImport.Year : x.recruit.RecruitImport.Year + 543).ToString() + : "", + number = x.score == null ? "" : x.score.Number, + }) .ToListAsync(); // --------------------------- @@ -2133,10 +2156,8 @@ namespace BMA.EHR.Recruit.Service.Controllers ProfileID = p.CitizenId, p.Prefix, FullName = $"{p.FirstName} {p.LastName}", - DateOfBirth = p.DateOfBirth != null - ? p.DateOfBirth != DateTime.MinValue - ? p.DateOfBirth.ToThaiShortDate() - : "" + DateOfBirth = p.DateOfBirth.HasValue && p.DateOfBirth.Value != DateTime.MinValue + ? p.DateOfBirth.Value.ToThaiShortDate() : "", Gender = p.Gendor, Degree = p.Educations.First().Degree, @@ -2150,7 +2171,11 @@ namespace BMA.EHR.Recruit.Service.Controllers : "" : "", ExamResult = sr == null ? "" : sr.ExamStatus, - ExamAttribute = _recruitService.CheckValidCertificate(p.Certificates.First().IssueDate, 5) ? "มีคุณสมบัติ" : "ไม่มีคุณสมบัติ", + ExamAttribute = p.Certificates.Count > 0 ? + _recruitService.CheckValidCertificate(p.Certificates.First().IssueDate, 5) + ? "มีคุณสมบัติ" + : "ไม่มีคุณสมบัติ" + : "ไม่มีคุณสมบัติ", IsSpecial = p.Isspecial, Remark = p.Remark, University = p.Educations.First().University, @@ -2852,10 +2877,8 @@ namespace BMA.EHR.Recruit.Service.Controllers ExamID = p.ExamId != null ? p.ExamId.ToThaiNumber() : "", CitizenId = p.CitizenId != null ? p.CitizenId.ToThaiNumber() : "", FullName = $"{p.Prefix}{p.FirstName} {p.LastName}", - DateOfBirth = p.DateOfBirth != null - ? p.DateOfBirth != DateTime.MinValue - ? p.DateOfBirth.ToThaiShortDate().ToString().ToThaiNumber() - : "" + DateOfBirth = p.DateOfBirth.HasValue && p.DateOfBirth.Value != DateTime.MinValue + ? p.DateOfBirth.Value.ToThaiShortDate().ToThaiNumber() : "", Gender = p.Gendor, Degree = p.Educations.First().Degree, diff --git a/Core/RequestLoggingMiddleware.cs b/Core/RequestLoggingMiddleware.cs index e43b8de..6c21f64 100644 --- a/Core/RequestLoggingMiddleware.cs +++ b/Core/RequestLoggingMiddleware.cs @@ -37,21 +37,32 @@ namespace BMA.EHR.Recruit.Service.Core { using (var client = new HttpClient()) { + // Set timeout to 30 seconds instead of default 100 seconds + client.Timeout = TimeSpan.FromSeconds(30); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Replace("Bearer ", "")); client.DefaultRequestHeaders.Add("api_key", apiKey); - var _res = await client.GetAsync(apiPath); + + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var _res = await client.GetAsync(apiPath, cts.Token); if (_res.IsSuccessStatusCode) { var _result = await _res.Content.ReadAsStringAsync(); - return _result; } return string.Empty; } } - catch + catch (TaskCanceledException) { - throw; + // Log timeout but don't throw - return empty result instead + Console.WriteLine($"API call timed out: {apiPath}"); + return string.Empty; + } + catch (Exception ex) + { + // Log other exceptions but don't throw - return empty result instead + Console.WriteLine($"API call failed: {apiPath}, Error: {ex.Message}"); + return string.Empty; } } @@ -60,10 +71,10 @@ namespace BMA.EHR.Recruit.Service.Core try { var apiPath = $"{_configuration["API"]}/org/dotnet/keycloak/{keycloakId}"; - var apiKey = _configuration["API_KEY"]; + var apiKey = _configuration["API_KEY"] ?? ""; var apiResult = await GetExternalAPIAsync(apiPath, accessToken ?? "", apiKey); - if (apiResult != null) + if (!string.IsNullOrEmpty(apiResult)) { var raw = JsonConvert.DeserializeObject(apiResult); if (raw != null) @@ -72,9 +83,11 @@ namespace BMA.EHR.Recruit.Service.Core return null; } - catch + catch (Exception ex) { - throw; + // Log exception but don't throw - return null instead + Console.WriteLine($"GetProfileByKeycloakIdAsync failed for {keycloakId}: {ex.Message}"); + return null; } } diff --git a/Migrations/20251016094447_update_nullable.Designer.cs b/Migrations/20251016094447_update_nullable.Designer.cs new file mode 100644 index 0000000..f4bcfa4 --- /dev/null +++ b/Migrations/20251016094447_update_nullable.Designer.cs @@ -0,0 +1,1601 @@ +// +using System; +using BMA.EHR.Recruit.Service.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace BMA.EHR.Recruit.Service.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20251016094447_update_nullable")] + partial class update_nullable + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.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("Documents"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("ApplyDate") + .HasColumnType("datetime(6)"); + + b.Property("CitizenCardExpireDate") + .HasColumnType("datetime(6)"); + + b.Property("CitizenCardIssuer") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("CitizenId") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("varchar(13)") + .HasComment("เลขประจำตัวประชาชน"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)") + .HasColumnOrder(100) + .HasComment("สร้างข้อมูลเมื่อ"); + + b.Property("CreatedDate") + .HasColumnType("datetime(6)"); + + 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("DateOfBirth") + .HasColumnType("datetime(6)"); + + b.Property("ExamId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("varchar(150)"); + + b.Property("Gendor") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("HddPosition") + .HasColumnType("longtext") + .HasComment("บัญชีสอบ"); + + b.Property("Isspecial") + .IsRequired() + .HasMaxLength(1) + .HasColumnType("varchar(1)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("varchar(150)"); + + 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("Marry") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("ModifiedDate") + .HasColumnType("datetime(6)"); + + b.Property("National") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("PositionLevel") + .HasColumnType("longtext"); + + b.Property("PositionName") + .HasColumnType("longtext"); + + b.Property("PositionType") + .HasColumnType("longtext"); + + b.Property("Prefix") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Qualified") + .IsRequired() + .HasMaxLength(1) + .HasColumnType("varchar(1)"); + + b.Property("Race") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RecruitImportId") + .HasColumnType("char(36)"); + + b.Property("RefNo") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("Religion") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Remark") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("typeTest") + .HasColumnType("longtext") + .HasComment("ประเภทการสอบภาค ก."); + + b.HasKey("Id"); + + b.HasIndex("RecruitImportId"); + + b.ToTable("Recruits"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Address1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Amphur") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Amphur1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + 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("District") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("District1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + 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("Mobile") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Moo") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Moo1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Province") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Province1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RecruitId") + .HasColumnType("char(36)"); + + b.Property("Road") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Road1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Soi") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Soi1") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Telephone") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ZipCode") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("varchar(5)"); + + b.Property("ZipCode1") + .IsRequired() + .HasMaxLength(5) + .HasColumnType("varchar(5)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitAddresses"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitCertificate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("CertificateNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + 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() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExpiredDate") + .HasColumnType("datetime(6)"); + + b.Property("IssueDate") + .HasColumnType("datetime(6)"); + + 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("RecruitId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitCertificates"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitDocument", 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("CreatedDate") + .HasColumnType("datetime(6)"); + + 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("DocumentFileId") + .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("RecruitId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("DocumentFileId"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitDocuments"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitEducation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("BachelorDate") + .HasColumnType("datetime(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("Degree") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("GPA") + .HasColumnType("double"); + + b.Property("HighDegree") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + 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("Major") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("MajorGroupId") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("varchar(20)"); + + b.Property("MajorGroupName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RecruitId") + .HasColumnType("char(36)"); + + b.Property("Specialist") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("varchar(1000)"); + + b.Property("University") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitEducations"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("AnnouncementDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(14) + .HasComment("วันที่ประกาศผลสอบ"); + + b.Property("AnnouncementEndDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(7) + .HasComment("วันสิ้นสุดประกาศ"); + + b.Property("AnnouncementStartDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(6) + .HasComment("วันเริ่มประกาศ"); + + b.Property("AuthName") + .HasColumnType("longtext"); + + b.Property("AuthPosition") + .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("Detail") + .HasColumnType("longtext") + .HasColumnOrder(4) + .HasComment("รายละเอียด"); + + b.Property("ExamDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(12) + .HasComment("วันที่สอบ"); + + b.Property("Fee") + .HasColumnType("int") + .HasColumnOrder(5) + .HasComment("ค่าธรรมเนียม"); + + b.Property("ImportFileId") + .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("Name") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("varchar(250)") + .HasColumnOrder(2) + .HasComment("รอบการสอบ"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnOrder(13) + .HasComment("หมายเหตุ"); + + b.Property("Order") + .HasColumnType("int") + .HasColumnOrder(3) + .HasComment("ครั้งที่"); + + b.Property("PaymentEndDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(9) + .HasComment("วันสิ้นสุดชำระเงิน"); + + b.Property("PaymentStartDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(8) + .HasComment("วันเริ่มชำระเงิน"); + + b.Property("RegisterEndDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(11) + .HasComment("วันสิ้นสุดสมัครสอบ"); + + b.Property("RegisterStartDate") + .HasColumnType("datetime(6)") + .HasColumnOrder(10) + .HasComment("วันเริ่มสมัครสอบ"); + + b.Property("Year") + .HasColumnType("int") + .HasColumnOrder(1) + .HasComment("ปีงบประมาณที่จัดสอบ"); + + b.HasKey("Id"); + + b.HasIndex("ImportFileId"); + + b.ToTable("RecruitImports"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportDocument", 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)") + .HasComment("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("RecruitImportId") + .HasColumnType("char(36)") + .HasComment("Id รอบสมัครสอบ"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("RecruitImportId"); + + b.ToTable("RecruitImportDocuments"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportHistory", 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") + .HasColumnOrder(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("RecruitImportId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitImportId"); + + b.ToTable("RecruitImportHistories"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportImage", 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)") + .HasComment("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("RecruitImportId") + .HasColumnType("char(36)") + .HasComment("Id รอบสมัครสอบ"); + + b.HasKey("Id"); + + b.HasIndex("DocumentId"); + + b.HasIndex("RecruitImportId"); + + b.ToTable("RecruitImportImages"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitOccupation", 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("Occupation") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Position") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RecruitId") + .HasColumnType("char(36)"); + + b.Property("Telephone") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("WorkAge") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Workplace") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitOccupations"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitPayment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("AccountNumber") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("BankCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ChequeNo") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ChqueBankCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CompanyCode") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + 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("CreditDebit") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CustomerName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + 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("PaymentId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PaymentType") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("RecruitId") + .HasColumnType("char(36)"); + + b.Property("RefNo1") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TellerId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TermBranch") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TextFile") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TransDate") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("TransTime") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("RecruitId"); + + b.ToTable("RecruitPayments"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitScore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)") + .HasColumnOrder(0) + .HasComment("PrimaryKey") + .HasAnnotation("Relational:JsonPropertyName", "id"); + + b.Property("ABStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง ผลประเมิน"); + + b.Property("AStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง ผลประเมิน"); + + b.Property("BStatus") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("CStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง ผลประเมิน"); + + b.Property("CitizenId") + .IsRequired() + .HasMaxLength(13) + .HasColumnType("varchar(13)") + .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("ExamId") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasComment("เลขประจำตัวสอบ"); + + b.Property("ExamStatus") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)") + .HasComment("สอบได้ / ตก / ขาดสอบ"); + + b.Property("FullA") + .HasColumnType("int") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง คะแนนเต็ม"); + + b.Property("FullB") + .HasColumnType("int"); + + b.Property("FullC") + .HasColumnType("int") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง ทดสอบสมรรถนะ+ทดสอบจิตวิทยาฯ คะแนนเต็ม"); + + b.Property("FullD") + .HasColumnType("int") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง สัมภาษณ์ คะแนนเต็ม"); + + b.Property("FullScore") + .HasColumnType("int") + .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("Major") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Number") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("varchar(200)") + .HasComment("ลำดับที่สอบได้"); + + b.Property("PercentageA") + .HasColumnType("double") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง ร้อยละ"); + + b.Property("PercentageB") + .HasColumnType("double"); + + b.Property("PercentageC") + .HasColumnType("double") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง ร้อยละ"); + + b.Property("RemarkExamOrder") + .IsRequired() + .HasColumnType("longtext") + .HasComment("หมายเหตุจากลำดับที่สอบได้"); + + b.Property("RemarkScore") + .IsRequired() + .HasColumnType("longtext") + .HasComment("หมายเหตุจากบัญชีรวมคะแนน"); + + b.Property("ScoreImportId") + .HasColumnType("char(36)"); + + b.Property("SumA") + .HasColumnType("double") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง คะแนนรวม"); + + b.Property("SumAB") + .HasColumnType("double") + .HasComment("ภาคความรู้ความสามารถที่ใช้เฉพาะตำแหน่ง คะแนนรวม"); + + b.Property("SumB") + .HasColumnType("double"); + + b.Property("SumC") + .HasColumnType("double") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง ทดสอบสมรรถนะ+ทดสอบจิตวิทยาฯ คะแนนรวม"); + + b.Property("SumCD") + .HasColumnType("double") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง คะแนนรวมทดสอบสมรรถนะ+ทดสอบจิตวิทยาฯ และสัมภาษณ์"); + + b.Property("SumD") + .HasColumnType("double") + .HasComment("ภาคความเหมาะสมกับตำแหน่ง สัมภาษณ์ คะแนนรวม"); + + b.Property("TotalScore") + .HasColumnType("double") + .HasComment("คะแนนรวม"); + + b.HasKey("Id"); + + b.HasIndex("ScoreImportId"); + + b.ToTable("RecruitScores"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.ScoreImport", 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("ImportFileId") + .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("RecruitImportId") + .HasColumnType("char(36)"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ImportFileId"); + + b.HasIndex("RecruitImportId") + .IsUnique(); + + b.ToTable("ScoreImports"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", "RecruitImport") + .WithMany("Recruits") + .HasForeignKey("RecruitImportId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("RecruitImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitAddress", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Addresses") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitCertificate", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Certificates") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitDocument", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Documents.Document", "DocumentFile") + .WithMany() + .HasForeignKey("DocumentFileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Documents") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DocumentFile"); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitEducation", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Educations") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Documents.Document", "ImportFile") + .WithMany() + .HasForeignKey("ImportFileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ImportFile"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportDocument", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Documents.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", "RecruitImport") + .WithMany("RecruitDocuments") + .HasForeignKey("RecruitImportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("RecruitImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportHistory", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", "RecruitImport") + .WithMany("ImportHostories") + .HasForeignKey("RecruitImportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("RecruitImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImportImage", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Documents.Document", "Document") + .WithMany() + .HasForeignKey("DocumentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", "RecruitImport") + .WithMany("RecruitImages") + .HasForeignKey("RecruitImportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Document"); + + b.Navigation("RecruitImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitOccupation", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Occupations") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitPayment", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", "Recruit") + .WithMany("Payments") + .HasForeignKey("RecruitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Recruit"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitScore", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.ScoreImport", "ScoreImport") + .WithMany("Scores") + .HasForeignKey("ScoreImportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ScoreImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.ScoreImport", b => + { + b.HasOne("BMA.EHR.Recruit.Service.Models.Documents.Document", "ImportFile") + .WithMany() + .HasForeignKey("ImportFileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", "RecruitImport") + .WithOne("ScoreImport") + .HasForeignKey("BMA.EHR.Recruit.Service.Models.Recruits.ScoreImport", "RecruitImportId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ImportFile"); + + b.Navigation("RecruitImport"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.Recruit", b => + { + b.Navigation("Addresses"); + + b.Navigation("Certificates"); + + b.Navigation("Documents"); + + b.Navigation("Educations"); + + b.Navigation("Occupations"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.RecruitImport", b => + { + b.Navigation("ImportHostories"); + + b.Navigation("RecruitDocuments"); + + b.Navigation("RecruitImages"); + + b.Navigation("Recruits"); + + b.Navigation("ScoreImport") + .IsRequired(); + }); + + modelBuilder.Entity("BMA.EHR.Recruit.Service.Models.Recruits.ScoreImport", b => + { + b.Navigation("Scores"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20251016094447_update_nullable.cs b/Migrations/20251016094447_update_nullable.cs new file mode 100644 index 0000000..7c1f3ea --- /dev/null +++ b/Migrations/20251016094447_update_nullable.cs @@ -0,0 +1,109 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace BMA.EHR.Recruit.Service.Migrations +{ + /// + public partial class update_nullable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "ModifiedDate", + table: "Recruits", + type: "datetime(6)", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime(6)"); + + migrationBuilder.AlterColumn( + name: "DateOfBirth", + table: "Recruits", + type: "datetime(6)", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime(6)"); + + migrationBuilder.AlterColumn( + name: "CitizenCardExpireDate", + table: "Recruits", + type: "datetime(6)", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime(6)"); + + migrationBuilder.AlterColumn( + name: "ApplyDate", + table: "Recruits", + type: "datetime(6)", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime(6)"); + + migrationBuilder.AlterColumn( + name: "BachelorDate", + table: "RecruitEducations", + type: "datetime(6)", + nullable: true, + oldClrType: typeof(DateTime), + oldType: "datetime(6)"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "ModifiedDate", + table: "Recruits", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime(6)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "DateOfBirth", + table: "Recruits", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime(6)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "CitizenCardExpireDate", + table: "Recruits", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime(6)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "ApplyDate", + table: "Recruits", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime(6)", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "BachelorDate", + table: "RecruitEducations", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), + oldClrType: typeof(DateTime), + oldType: "datetime(6)", + oldNullable: true); + } + } +} diff --git a/Migrations/ApplicationDbContextModelSnapshot.cs b/Migrations/ApplicationDbContextModelSnapshot.cs index 0e0b6c4..ce93624 100644 --- a/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Migrations/ApplicationDbContextModelSnapshot.cs @@ -62,10 +62,10 @@ namespace BMA.EHR.Recruit.Service.Migrations .HasComment("PrimaryKey") .HasAnnotation("Relational:JsonPropertyName", "id"); - b.Property("ApplyDate") + b.Property("ApplyDate") .HasColumnType("datetime(6)"); - b.Property("CitizenCardExpireDate") + b.Property("CitizenCardExpireDate") .HasColumnType("datetime(6)"); b.Property("CitizenCardIssuer") @@ -101,7 +101,7 @@ namespace BMA.EHR.Recruit.Service.Migrations .HasColumnOrder(101) .HasComment("User Id ที่สร้างข้อมูล"); - b.Property("DateOfBirth") + b.Property("DateOfBirth") .HasColumnType("datetime(6)"); b.Property("ExamId") @@ -157,7 +157,7 @@ namespace BMA.EHR.Recruit.Service.Migrations .HasMaxLength(20) .HasColumnType("varchar(20)"); - b.Property("ModifiedDate") + b.Property("ModifiedDate") .HasColumnType("datetime(6)"); b.Property("National") @@ -512,7 +512,7 @@ namespace BMA.EHR.Recruit.Service.Migrations .HasComment("PrimaryKey") .HasAnnotation("Relational:JsonPropertyName", "id"); - b.Property("BachelorDate") + b.Property("BachelorDate") .HasColumnType("datetime(6)"); b.Property("CreatedAt") diff --git a/Models/Recruits/Recruit.cs b/Models/Recruits/Recruit.cs index 1585370..b449adf 100644 --- a/Models/Recruits/Recruit.cs +++ b/Models/Recruits/Recruit.cs @@ -33,8 +33,8 @@ namespace BMA.EHR.Recruit.Service.Models.Recruits [MaxLength(200)] public string Religion { get; set; } = string.Empty; - [Required] - public DateTime DateOfBirth { get; set; } + //[Required] + public DateTime? DateOfBirth { get; set; } [MaxLength(20)] public string Marry { get; set; } = string.Empty; @@ -48,7 +48,7 @@ namespace BMA.EHR.Recruit.Service.Models.Recruits [MaxLength(200)] public string CitizenCardIssuer { get; set; } = string.Empty; - public DateTime CitizenCardExpireDate { get; set; } + public DateTime? CitizenCardExpireDate { get; set; } [MaxLength(200)] public string Remark { get; set; } = string.Empty; @@ -72,9 +72,9 @@ namespace BMA.EHR.Recruit.Service.Models.Recruits public DateTime CreatedDate { get; set; } = DateTime.Now; - public DateTime ModifiedDate { get; set; } + public DateTime? ModifiedDate { get; set; } - public DateTime ApplyDate { get; set; } + public DateTime? ApplyDate { get; set; } public string? PositionName { get; set; } public string? PositionType { get; set; } diff --git a/Models/Recruits/RecruitEducation.cs b/Models/Recruits/RecruitEducation.cs index 805e795..af7172d 100644 --- a/Models/Recruits/RecruitEducation.cs +++ b/Models/Recruits/RecruitEducation.cs @@ -26,7 +26,7 @@ namespace BMA.EHR.Recruit.Service.Models.Recruits [MaxLength(200)] public string HighDegree { get; set; } - public DateTime BachelorDate { get; set; } + public DateTime? BachelorDate { get; set; } public Recruit Recruit { get; set; } } diff --git a/Program.cs b/Program.cs index 03d40d2..67fee6f 100644 --- a/Program.cs +++ b/Program.cs @@ -67,6 +67,12 @@ builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); +// Configure HttpClient with timeout +builder.Services.AddHttpClient("default", client => +{ + client.Timeout = TimeSpan.FromSeconds(30); +}); + // use serilog //ConfigureLogs(); //builder.Host.UseSerilog(); @@ -107,10 +113,6 @@ builder.Services.AddSwaggerGen(); builder.Services.ConfigureOptions(); builder.Services.AddHealthChecks(); -// Register Service -builder.Services.AddTransient(); -builder.Services.AddTransient(); - var app = builder.Build(); var apiVersionDescriptionProvider = app.Services.GetRequiredService(); @@ -133,12 +135,11 @@ app.UseHttpsRedirection(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); +app.UseMiddleware(); app.UseDefaultFiles(); app.UseStaticFiles(); app.MapControllers(); -app.UseMiddleware(); - // apply migrations await using var scope = app.Services.CreateAsyncScope(); await using var db = scope.ServiceProvider.GetRequiredService(); diff --git a/Services/RecruitService.cs b/Services/RecruitService.cs index e4b1bea..620ac18 100644 --- a/Services/RecruitService.cs +++ b/Services/RecruitService.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -23,6 +24,7 @@ namespace BMA.EHR.Recruit.Service.Services private readonly MetadataDbContext _contextMetadata; private readonly OrgDbContext _contextOrg; private readonly MinIOService _minIOService; + private readonly IHttpClientFactory _httpClientFactory; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IConfiguration _configuration; @@ -31,12 +33,14 @@ namespace BMA.EHR.Recruit.Service.Services OrgDbContext contextOrg, IHttpContextAccessor httpContextAccessor, MinIOService minIOService, - IConfiguration configuration) + IConfiguration configuration, + IHttpClientFactory httpClientFactory) { _context = context; _contextMetadata = contextMetadata; _contextOrg = contextOrg; _minIOService = minIOService; + _httpClientFactory = httpClientFactory; _httpContextAccessor = httpContextAccessor; _configuration = configuration; } @@ -180,13 +184,25 @@ namespace BMA.EHR.Recruit.Service.Services { try { - // 🚀 Prepare HTTP client once - var httpClient1 = new HttpClient(); - httpClient1.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "")); - httpClient1.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + // 🚀 Prepare HTTP client once via factory with timeout + var clientForPos = _httpClientFactory.CreateClient("default"); + clientForPos.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "")); + clientForPos.DefaultRequestHeaders.Remove("api_key"); + clientForPos.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"] ?? ""); var apiUrl1 = $"{_configuration["API"]}/org/pos/level"; - var response1 = await httpClient1.GetStringAsync(apiUrl1); - var posOptions = JsonConvert.DeserializeObject(response1); + var response1 = string.Empty; + try + { + using var ctsPos = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + response1 = await clientForPos.GetStringAsync(apiUrl1, ctsPos.Token); + } + catch (TaskCanceledException) + { + // timeout - fallback to empty posOptions + response1 = string.Empty; + } + + var posOptions = string.IsNullOrWhiteSpace(response1) ? null : JsonConvert.DeserializeObject(response1); var recruitImport = await _context.RecruitImports.AsQueryable() .FirstOrDefaultAsync(x => x.Id == examId); @@ -245,26 +261,41 @@ namespace BMA.EHR.Recruit.Service.Services .Where(x => !string.IsNullOrWhiteSpace(x.ExamId)) .ToDictionary(x => x.ExamId, x => x); - // 🚀 Prepare HTTP client once - var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "")); - httpClient.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]); + // 🚀 Batch HTTP requests using IHttpClientFactory with concurrency limit and cancellation + var clientForOrg = _httpClientFactory.CreateClient("default"); + clientForOrg.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "")); + clientForOrg.DefaultRequestHeaders.Remove("api_key"); + clientForOrg.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"] ?? ""); - // 🚀 Batch HTTP requests + var semaphore = new SemaphoreSlim(10); // limit concurrency var orgTasks = candidates.Select(async candidate => { if (string.IsNullOrWhiteSpace(candidate.CitizenId)) return new { CitizenId = candidate.CitizenId ?? "", org = (dynamic?)null }; - var apiUrl = $"{_configuration["API"]}/org/profile/citizenid/position/{candidate.CitizenId}"; + await semaphore.WaitAsync(); try { - var response = await httpClient.GetStringAsync(apiUrl); - return new { CitizenId = candidate.CitizenId, org = JsonConvert.DeserializeObject(response) }; + var apiUrl = $"{_configuration["API"]}/org/profile/citizenid/position/{candidate.CitizenId}"; + try + { + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var response = await clientForOrg.GetStringAsync(apiUrl, cts.Token); + return new { CitizenId = candidate.CitizenId, org = JsonConvert.DeserializeObject(response) }; + } + catch (TaskCanceledException) + { + // timeout + return new { CitizenId = candidate.CitizenId ?? "", org = (dynamic?)null }; + } + catch (Exception) + { + return new { CitizenId = candidate.CitizenId ?? "", org = (dynamic?)null }; + } } - catch + finally { - return new { CitizenId = candidate.CitizenId ?? "", org = (dynamic?)null }; + semaphore.Release(); } }).ToList(); @@ -274,7 +305,8 @@ namespace BMA.EHR.Recruit.Service.Services // 🚀 Prepare batch inserts var placementProfiles = new List(); var placementEducations = new List(); - var placementCertificates = new List(); + /*Comment ข้อมูลใบประกอบวิชาชีพ เพราะในไฟล์นำเข้ายังไม่มีคอลัมน์ที่ระบุข้อมูลส่วนนี้*/ + //var placementCertificates = new List(); foreach (var candidate in candidates) { @@ -417,33 +449,33 @@ namespace BMA.EHR.Recruit.Service.Services LastUpdateFullName = FullName ?? "", }; placementEducations.Add(placementEducation); - - var placementCertificate = new PlacementCertificate - { - PlacementProfile = placementProfile, - CertificateNo = firstCertificate?.CertificateNo ?? "", - IssueDate = firstCertificate?.IssueDate, - ExpireDate = firstCertificate?.ExpiredDate, - CertificateType = firstCertificate?.Description ?? "", - CreatedAt = DateTime.Now, - CreatedUserId = UserId ?? "", - LastUpdatedAt = DateTime.Now, - LastUpdateUserId = UserId ?? "", - CreatedFullName = FullName ?? "", - LastUpdateFullName = FullName ?? "", - }; - placementCertificates.Add(placementCertificate); + /*Comment ข้อมูลใบประกอบวิชาชีพ เพราะในไฟล์นำเข้ายังไม่มีคอลัมน์ที่ระบุข้อมูลส่วนนี้*/ + //var placementCertificate = new PlacementCertificate + //{ + // PlacementProfile = placementProfile, + // CertificateNo = firstCertificate?.CertificateNo ?? "", + // IssueDate = firstCertificate?.IssueDate, + // ExpireDate = firstCertificate?.ExpiredDate, + // CertificateType = firstCertificate?.Description ?? "", + // CreatedAt = DateTime.Now, + // CreatedUserId = UserId ?? "", + // LastUpdatedAt = DateTime.Now, + // LastUpdateUserId = UserId ?? "", + // CreatedFullName = FullName ?? "", + // LastUpdateFullName = FullName ?? "", + //}; + //placementCertificates.Add(placementCertificate); } // 🚀 Batch insert all records await _contextMetadata.PlacementProfiles.AddRangeAsync(placementProfiles); await _contextMetadata.PlacementEducations.AddRangeAsync(placementEducations); - await _contextMetadata.PlacementCertificates.AddRangeAsync(placementCertificates); + /*Comment ข้อมูลใบประกอบวิชาชีพ เพราะในไฟล์นำเข้ายังไม่มีคอลัมน์ที่ระบุข้อมูลส่วนนี้*/ + //await _contextMetadata.PlacementCertificates.AddRangeAsync(placementCertificates); // 🚀 Single SaveChanges at the end await _contextMetadata.SaveChangesAsync(); - httpClient.Dispose(); } catch { @@ -460,13 +492,13 @@ namespace BMA.EHR.Recruit.Service.Services if (!string.IsNullOrWhiteSpace(road)) parts.Add($"ถนน {road}"); return string.Join(" ", parts); } - public DateTime CheckDateTime(string Date, string Formate) + public DateTime? CheckDateTime(string Date, string Formate) { // ตอนนี้ทำไว้ให้รองรับแค่ "dd/MM/yyyy", "yyyy-MM-dd" Date = Date.Trim(); if (string.IsNullOrWhiteSpace(Date)) - return DateTime.MinValue; + return null; // จะเข้าเฉพาะกรณีที่ string เป็นตัวเลข เช่น "35635", "44561.5" if (double.TryParse(Date, out double oaDate)) @@ -484,7 +516,7 @@ namespace BMA.EHR.Recruit.Service.Services string[] parts = Date.Trim().Replace("-", "/").Split("/"); if (parts.Length != 3) - return DateTime.MinValue; + return null; int year; int month; @@ -498,14 +530,14 @@ namespace BMA.EHR.Recruit.Service.Services } else if (!int.TryParse(parts[2], out year)) { - return DateTime.MinValue; + return null; } if (!int.TryParse(parts[1], out month)) - return DateTime.MinValue; + return null; if (!int.TryParse(parts[0], out day)) - return DateTime.MinValue; + return null; break; @@ -516,18 +548,18 @@ namespace BMA.EHR.Recruit.Service.Services } else if (!int.TryParse(parts[0], out year)) { - return DateTime.MinValue; + return null; } if (!int.TryParse(parts[1], out month)) - return DateTime.MinValue; + return null; if (!int.TryParse(parts[2], out day)) - return DateTime.MinValue; + return null; break; default: - return DateTime.MinValue; + return null; } if (month < 1 || month > 12) @@ -540,13 +572,13 @@ namespace BMA.EHR.Recruit.Service.Services else if (day > maxDay) day = maxDay; - var normalDate = $"{day}/{(month >= 1 && month <= 9 ? $"0{month}" : month)}/{year}"; + var normalDate = $"{(day >= 1 && day <= 9 ? $"0{day}" : day)}/{(month >= 1 && month <= 9 ? $"0{month}" : month)}/{year}"; if (DateTime.TryParseExact(normalDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedDate)) { return parsedDate; } - return DateTime.MinValue; + return null; } } } \ No newline at end of file