From 125dd593487692fc11ae778b2bc84e78dfafff5d Mon Sep 17 00:00:00 2001 From: Bright Date: Wed, 17 Sep 2025 11:58:54 +0700 Subject: [PATCH] =?UTF-8?q?report=20=E0=B8=A3=E0=B8=B2=E0=B8=A2=E0=B8=8A?= =?UTF-8?q?=E0=B8=B7=E0=B9=88=E0=B8=AD=E0=B8=9C=E0=B8=B9=E0=B9=89=E0=B8=AA?= =?UTF-8?q?=E0=B8=A1=E0=B8=B1=E0=B8=84=E0=B8=A3=E0=B8=AA=E0=B8=AD=E0=B8=9A?= =?UTF-8?q?=E0=B8=84=E0=B8=B1=E0=B8=94=E0=B9=80=E0=B8=A5=E0=B8=B7=E0=B8=AD?= =?UTF-8?q?=E0=B8=81=E0=B8=9C=E0=B8=B9=E0=B9=89=E0=B8=9E=E0=B8=B4=E0=B8=81?= =?UTF-8?q?=E0=B8=B2=E0=B8=A3=20(generate=20=E0=B8=95=E0=B8=A3=E0=B8=87)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Controllers/DisableReportController.cs | 133 +++++++++++++++++++++++++ Core/RequestLoggingMiddleware.cs | 67 +++++++++++-- 2 files changed, 190 insertions(+), 10 deletions(-) diff --git a/Controllers/DisableReportController.cs b/Controllers/DisableReportController.cs index 0b699ff..81bf835 100644 --- a/Controllers/DisableReportController.cs +++ b/Controllers/DisableReportController.cs @@ -12,6 +12,10 @@ using Telerik.Reporting; using Telerik.Reporting.Processing; using BMA.EHR.Recurit.Exam.Service.Response; using BMA.EHR.Recurit.Exam.Service.Models; +using OfficeOpenXml.Style; +using OfficeOpenXml; +using System.Drawing; +using Nest; namespace BMA.EHR.Recurit.Exam.Service.Controllers { @@ -251,6 +255,135 @@ namespace BMA.EHR.Recurit.Exam.Service.Controllers } } + /// + /// รายงานรายชื่อผู้มีสิทธิ์สอบ + /// + /// รหัสรอบการสอบแข่งขัน + /// + [HttpGet("candidate-new/{id:length(36)}")] + public async Task GetCandidateNewListReportAsync(Guid id) + { + var data = await _context.Disables.AsQueryable() + .Include(x => x.PeriodExam) + .Where(x => x.PeriodExam.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.PeriodExam.Name} ครั้งที่ {(p.PeriodExam != null ? p.PeriodExam.Round.ToString().ToThaiNumber() : "")}/{(p.PeriodExam.Year > 2500 ? p.PeriodExam.Year.ToString().ToThaiNumber() : (p.PeriodExam.Year+543).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 } } diff --git a/Core/RequestLoggingMiddleware.cs b/Core/RequestLoggingMiddleware.cs index abbd615..c26cce0 100644 --- a/Core/RequestLoggingMiddleware.cs +++ b/Core/RequestLoggingMiddleware.cs @@ -165,19 +165,66 @@ namespace BMA.EHR.Recurit.Exam.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"; } }