diff --git a/BMA.EHR.Application/Repositories/PlacementRepository.cs b/BMA.EHR.Application/Repositories/PlacementRepository.cs index 82b71b79..2b40d702 100644 --- a/BMA.EHR.Application/Repositories/PlacementRepository.cs +++ b/BMA.EHR.Application/Repositories/PlacementRepository.cs @@ -8,6 +8,17 @@ using Newtonsoft.Json; namespace BMA.EHR.Application.Repositories { + /// + /// Response model จาก Org API (check-isLeave) + /// + public class OrgProfileResult + { + public string citizenId { get; set; } = ""; + public string? profileId { get; set; } + public bool isLeave { get; set; } + public bool isActive { get; set; } + } + public class PlacementRepository : GenericRepository { #region " Fields " @@ -83,39 +94,43 @@ namespace BMA.EHR.Application.Repositories /// /// Job อัพเดทสถานะผู้สอบผ่านที่ลาออกไปแล้วแต่ยังไม่ส่งไปออกคำสั่ง + /// และอัพเดทบุคคลภายนอกที่เข้ามาอยู่ในระบบแล้ว /// ทำงานทุกวันเวลา 05:00 น. /// public async Task UpdateStatusPlacementProfiles() { Console.WriteLine("[Job:UpdateStatusPlacementProfiles] === STARTED ==="); - var officerProfileIds = await _dbContext.Set() - .Where(p => !string.IsNullOrEmpty(p.profileId) - && p.IsOfficer == true + // 1. Query ทั้ง 2 กรณี: ทุกคนที่ยังไม่ DONE + var allCitizenIds = await _dbContext.Set() + .Where(p => !string.IsNullOrEmpty(p.CitizenId) && p.PlacementStatus != "DONE" - // && p.Id == Guid.Parse("08deb7de-3030-4d1b-8519-8148584949fc") + // && p.CitizenId == "2536721883131" ) - .Select(p => p.profileId) + .Select(p => new { p.CitizenId, p.IsOfficer }) .ToListAsync(); - if (!officerProfileIds.Any()) + if (!allCitizenIds.Any()) { Console.WriteLine("[Job:UpdateStatusPlacementProfiles] No profiles to process"); return; } - Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] พบข้าราชการที่สอบผ่านทั้งหมด {officerProfileIds.Count} คน ที่ยังไม่ส่งไปออกคำสั่ง"); + var officerCount = allCitizenIds.Count(x => x.IsOfficer == true); + var notOfficerCount = allCitizenIds.Count(x => x.IsOfficer == false); + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] พบข้าราชการ {officerCount} คน, บุคคลภายนอก {notOfficerCount} คน"); + // 2. ส่ง citizenIds ทั้งหมดไป Org API ครั้งเดียว + var citizenIds = allCitizenIds.Select(x => x.CitizenId).Distinct().ToList(); var apiUrl = $"{_configuration["API"]}/org/dotnet/check-isLeave"; - List leaveProfileIds = new(); + + List orgResults = new(); using (var client = new HttpClient()) { client.DefaultRequestHeaders.Add("api-key", _configuration["API_KEY"]); - var payload = new - { - profileIds = officerProfileIds.Distinct().ToList() - }; + + var payload = new { citizenIds }; var jsonPayload = JsonConvert.SerializeObject(payload); var content = new StringContent(jsonPayload, System.Text.Encoding.UTF8, "application/json"); @@ -123,15 +138,16 @@ namespace BMA.EHR.Application.Repositories { var response = await client.PostAsync(apiUrl, content); var result = await response.Content.ReadAsStringAsync(); + var responseObj = JsonConvert.DeserializeAnonymousType(result, new { status = 0, message = "", - result = new List() + result = new List() }); - leaveProfileIds = responseObj.result ?? new(); - Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] พบ {leaveProfileIds.Count} รายการที่ลาออก"); + orgResults = responseObj?.result ?? new(); + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] Org API ตอบกลับ {orgResults.Count} รายการ"); } catch (Exception ex) { @@ -140,18 +156,35 @@ namespace BMA.EHR.Application.Repositories } } - if (leaveProfileIds.Any()) + if (!orgResults.Any()) { - var batchSize = 500; - var totalUpdated = 0; - var totalBatches = (int)Math.Ceiling((double)leaveProfileIds.Count / batchSize); + Console.WriteLine("[Job:UpdateStatusPlacementProfiles] ไม่มีรายการต้องอัปเดต"); + Console.WriteLine("[Job:UpdateStatusPlacementProfiles] === COMPLETED ==="); + return; + } + // 3. แยกข้อมูลตามเงื่อนไข + var leaveCitizenIds = orgResults.Where(x => x.isLeave).Select(x => x.citizenId).ToList(); + var inSystemProfiles = orgResults.Where(x => x.isActive && !x.isLeave && !string.IsNullOrEmpty(x.profileId)).ToList(); + + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] ลาออก {leaveCitizenIds.Count} รายการ, อยู่ที่ทะเบียนประวัติ {inSystemProfiles.Count} รายการ"); + + // 4. Split Batch Update (500 รายการ/batch) + var batchSize = 500; + var totalUpdated = 0; + + // 4.1 Update คนลาออก → IsOfficer = false + if (leaveCitizenIds.Any()) + { + var totalBatches = (int)Math.Ceiling((double)leaveCitizenIds.Count / batchSize); for (int i = 0; i < totalBatches; i++) { - var batch = leaveProfileIds.Skip(i * batchSize).Take(batchSize).ToList(); + var batch = leaveCitizenIds.Skip(i * batchSize).Take(batchSize).ToList(); var profilesToUpdate = await _dbContext.Set() - .Where(p => !string.IsNullOrEmpty(p.profileId) && batch.Contains(p.profileId)) + .Where(p => !string.IsNullOrEmpty(p.CitizenId) + && batch.Contains(p.CitizenId) + && p.IsOfficer == true) .ToListAsync(); foreach (var profile in profilesToUpdate) @@ -160,12 +193,43 @@ namespace BMA.EHR.Application.Repositories } await _dbContext.SaveChangesAsync(); - totalUpdated += profilesToUpdate.Count; - Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] Batch {i + 1}/{totalBatches} → อัปเดต {profilesToUpdate.Count} รายการ"); + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] [ลาออก] Batch {i + 1}/{totalBatches} → อัปเดต {profilesToUpdate.Count} รายการ"); } - Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] อัปเดตรวมทั้งหมด {totalUpdated} รายการ → IsOfficer = false"); } + + // 4.2 Update คนที่อยู่ในทะเบียนประวัติ → profileId + IsOfficer = true + if (inSystemProfiles.Any()) + { + var totalBatches = (int)Math.Ceiling((double)inSystemProfiles.Count / batchSize); + for (int i = 0; i < totalBatches; i++) + { + var batch = inSystemProfiles.Skip(i * batchSize).Take(batchSize).ToList(); + var batchCitizenIds = batch.Select(x => x.citizenId).ToList(); + + var profilesToUpdate = await _dbContext.Set() + .Where(p => !string.IsNullOrEmpty(p.CitizenId) + && batchCitizenIds.Contains(p.CitizenId) + && p.IsOfficer == false) + .ToListAsync(); + + foreach (var profile in profilesToUpdate) + { + var orgProfile = batch.FirstOrDefault(x => x.citizenId == profile.CitizenId); + if (orgProfile != null) + { + profile.profileId = orgProfile.profileId; + profile.IsOfficer = true; + } + } + + await _dbContext.SaveChangesAsync(); + totalUpdated += profilesToUpdate.Count; + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] [เข้าระบบ] Batch {i + 1}/{totalBatches} → อัปเดต {profilesToUpdate.Count} รายการ"); + } + } + + Console.WriteLine($"[Job:UpdateStatusPlacementProfiles] อัปเดตรวมทั้งหมด {totalUpdated} รายการ"); Console.WriteLine("[Job:UpdateStatusPlacementProfiles] === COMPLETED ==="); }