diff --git a/Controllers/RecruitController.cs b/Controllers/RecruitController.cs index ad5b0f7..3c74673 100644 --- a/Controllers/RecruitController.cs +++ b/Controllers/RecruitController.cs @@ -28,6 +28,8 @@ using System.Security.Claims; using System.Text; using static System.Runtime.InteropServices.JavaScript.JSType; using System.Globalization; +using OfficeOpenXml.Style; +using System.Drawing; namespace BMA.EHR.Recruit.Service.Controllers { @@ -1839,7 +1841,7 @@ namespace BMA.EHR.Recruit.Service.Controllers ExamName = p.RecruitImport!.Name, ExamOrder = p.RecruitImport.Order, ExamYear = p.RecruitImport.Year.ToThaiYear(), - Score = sr == null ? 0.0 : sr.SumA + sr.SumB + sr.SumC, + Score = sr == null ? 0.0 : sr.TotalScore, Number = sr == null ? "" : sr.Number, ExamCount = _recruitService.GetExamCount(p.CitizenId), ScoreExpire = p.RecruitImport.AnnouncementDate == null @@ -2542,7 +2544,6 @@ namespace BMA.EHR.Recruit.Service.Controllers University = p.Educations.First().University, PositionName = p.PositionName, ExamName = $"{p.RecruitImport!.Name} ครั้งที่ {p.RecruitImport.Order}/{p.RecruitImport.Year.ToThaiYear()}".ToThaiNumber(), - ExamCount = _recruitService.GetExamCount(p.CitizenId).ToString().ToThaiNumber(), type = p.typeTest == "bangkok" ? "กทม." : p.typeTest == "ocsc" ? "ก.พ." : "", FA = sr.FullA != null ? sr.FullA.ToString().ToThaiNumber() : "", @@ -2576,6 +2577,136 @@ namespace BMA.EHR.Recruit.Service.Controllers return Error(ex); } } + + /// + /// รายงานรายชื่อผู้มีสิทธิ์สอบ + /// + /// รหัสรอบการสอบแข่งขัน + /// + [HttpGet("report/candidate-new/{id:length(36)}")] + public async Task GetCandidateNewListReportAsync(Guid id) + { + var data = await _context.Recruits.AsQueryable() + .Include(x => x.RecruitImport) + .Where(x => x.RecruitImport.Id == id) + .OrderBy(x => x.ExamId) + .Select(p => new + { + FullName = $"{p.Prefix}{p.FirstName} {p.LastName}", + PositionName = p.PositionName, + Remark = p.Remark != null ? p.Remark.ToThaiNumber() : "", + RefNo1 = p.Payments.Select(x => x.RefNo1).FirstOrDefault() != null + ? p.Payments.Select(x => x.RefNo1).FirstOrDefault().ToThaiNumber() + : "", + ExamName = + $"ครั้งที่ {(p.RecruitImport != null ? p.RecruitImport.Order.ToString().ToThaiNumber() : "")}/{(p.RecruitImport != null ? p.RecruitImport.Year.ToThaiYear().ToString().ToThaiNumber() : "")}", + }).ToListAsync(); + + if (data.Count == 0) + { + return NotFound(new { Message = "ไม่พบข้อมูลในระบบ" }); + } + + var examName = data[0].ExamName; + + var groupData = data + .GroupBy(x => x.PositionName) + .Select(g => new + { + PositionName = $"ตำแหน่ง {g.Key}", + Total = $"จำนวน {g.Count().ToString().ToThaiNumber()} ราย", + Persons = g.Select((x, index) => new + { + No = (index + 1).ToString().ToThaiNumber(), + RefNo1 = x.RefNo1, + FullName = x.FullName, + Remark = x.Remark + }).ToList() + }) + .ToList(); + + using var package = new ExcelPackage(); + var ws = package.Workbook.Worksheets.Add(examName); + // ตั้งค่า Font ทั้ง sheet + ws.Cells.Style.Font.Name = "TH Sarabun PSK"; + ws.Cells.Style.Font.Size = 14; + int row = 1; + + // ======= Header ======= + ws.Cells[row, 1, row + 2, 4].Merge = true; + ws.Cells[row, 1].Value = $"รายชื่อผู้ชำระค่าธรรมเนียมการสมัครสอบการแข่งขันเพื่อบรรจุและแต่งตั้งบุคคล" + + $"เข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ {examName}"; + + ws.Cells[row, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; + ws.Cells[row, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; + ws.Cells[row, 1].Style.Font.Bold = true; + ws.Cells[row, 1].Style.WrapText = true; + + row += 4; + + foreach (var group in groupData) + { + // ======= Position Header ======= + ws.Cells[row, 1, row + 1, 4].Merge = true; // merge 2 แถว และ column A-D + ws.Cells[row, 1].Value = $"{group.PositionName}\n{group.Total}"; + ws.Cells[row, 1].Style.Font.Bold = true; + ws.Cells[row, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + ws.Cells[row, 1].Style.VerticalAlignment = ExcelVerticalAlignment.Center; + ws.Cells[row, 1].Style.WrapText = true; + + row += 2; // ขยับ row ไปหลัง header ที่ merge 2 แถว + + // ======= Table Header ======= + ws.Cells[row, 1].Value = "ลำดับ"; + ws.Cells[row, 2].Value = "เลขอ้างอิง"; + ws.Cells[row, 3].Value = "ชื่อ-สกุล"; + ws.Cells[row, 4].Value = "หมายเหตุ"; + + ws.Cells[row, 1, row, 4].Style.Font.Bold = true; + ws.Cells[row, 1, row, 4].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + ws.Cells[row, 1, row, 4].Style.VerticalAlignment = ExcelVerticalAlignment.Center; + ws.Cells[row, 1, row, 4].Style.Fill.PatternType = ExcelFillStyle.Solid; + ws.Cells[row, 1, row, 4].Style.Fill.BackgroundColor.SetColor(Color.LightGray); + + row++; + + // ======= Table Detail ======= + foreach (var person in group.Persons) + { + ws.Cells[row, 1].Value = person.No; + ws.Cells[row, 2].Value = person.RefNo1; + ws.Cells[row, 3].Value = person.FullName; + ws.Cells[row, 4].Value = person.Remark; + + // จัดกลางเฉพาะ No และ RefNo1 + ws.Cells[row, 1, row, 2].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; + ws.Cells[row, 1, row, 2].Style.VerticalAlignment = ExcelVerticalAlignment.Center; + + // เพิ่มกรอบให้แต่ละ cell + for (int col = 1; col <= 4; col++) + { + ws.Cells[row, col].Style.Border.Top.Style = ExcelBorderStyle.Thin; + ws.Cells[row, col].Style.Border.Bottom.Style = ExcelBorderStyle.Thin; + ws.Cells[row, col].Style.Border.Left.Style = ExcelBorderStyle.Thin; + ws.Cells[row, col].Style.Border.Right.Style = ExcelBorderStyle.Thin; + } + + row++; + } + + row++; + } + + ws.Cells.AutoFitColumns(); + + var fileBytes = package.GetAsByteArray(); + var fileName = $"รายชื่อผู้สอบ_{examName}.xlsx"; + + return File(fileBytes, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + fileName); + } + #endregion #endregion diff --git a/Core/RequestLoggingMiddleware.cs b/Core/RequestLoggingMiddleware.cs index fe87828..e43b8de 100644 --- a/Core/RequestLoggingMiddleware.cs +++ b/Core/RequestLoggingMiddleware.cs @@ -165,22 +165,68 @@ namespace BMA.EHR.Recruit.Service.Core // อ่านข้อมูลจาก Response หลังจากที่ได้ถูกส่งออกไป memoryStream.Seek(0, SeekOrigin.Begin); var responseBody = new StreamReader(memoryStream).ReadToEnd(); - if (responseBody != "") - responseBodyJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBody), new JsonSerializerOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, WriteIndented = true, Converters = { new DateTimeFixConverter() } }); + //if (responseBody != "") + // responseBodyJson = JsonSerializer.Serialize(JsonSerializer.Deserialize(responseBody), new JsonSerializerOptions { Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, WriteIndented = true, Converters = { new DateTimeFixConverter() } }); - var json = JsonSerializer.Deserialize(responseBody); - if(json.ValueKind == JsonValueKind.Array) + //var json = JsonSerializer.Deserialize(responseBody); + //if(json.ValueKind == JsonValueKind.Array) + //{ + // message = "success"; + //} + //else + //{ + // if (json.TryGetProperty("message", out var messageElement)) + // { + // message = messageElement.GetString(); + // } + //} + + if (!string.IsNullOrEmpty(responseBody)) { - message = "success"; - } - else - { - if (json.TryGetProperty("message", out var messageElement)) + var contentType = context.Response.ContentType ?? ""; + + if (contentType.Equals( + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + StringComparison.OrdinalIgnoreCase)) { - message = messageElement.GetString(); + // Excel + responseBodyJson = $"Excel file (Length={memoryStream.Length} bytes)"; + message = "success"; + } + else if (contentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) + { + // JSON + try + { + responseBodyJson = JsonSerializer.Serialize( + JsonSerializer.Deserialize(responseBody), + new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + WriteIndented = true, + Converters = { new DateTimeFixConverter() } + }); + + var json = JsonSerializer.Deserialize(responseBody); + if (json.ValueKind == JsonValueKind.Array) + message = "success"; + else if (json.TryGetProperty("message", out var messageElement)) + message = messageElement.GetString(); + } + catch + { + // fallback ถ้า deserialize ไม่ได้ + responseBodyJson = responseBody; + message = "success"; + } + } + else + { + // plain text / HTML / binary อื่น + responseBodyJson = responseBody; + message = "success"; } } - var logData = new {