diff --git a/Controllers/ExamReportController.cs b/Controllers/ExamReportController.cs index 91fde03..aee878d 100644 --- a/Controllers/ExamReportController.cs +++ b/Controllers/ExamReportController.cs @@ -666,7 +666,7 @@ namespace BMA.EHR.Report.Service.Controllers } /// - /// รายชื่อผู้มีสิทธิ์สอบ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือกผู้พิการ) + /// รายชื่อผู้มีสิทธิ์สอบ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือกอื่นๆ) /// /// รหัสรอบการสอบ /// @@ -796,7 +796,7 @@ namespace BMA.EHR.Report.Service.Controllers } /// - /// รายชื่อผู้สอบแข่งขันได้ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือกผู้พิการ) + /// รายชื่อผู้สอบคัดเลือกได้ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือกอื่นๆ) /// /// รหัสรอบการสอบ /// @@ -871,7 +871,7 @@ namespace BMA.EHR.Report.Service.Controllers document.SetFont(font).SetFontSize(16); document.SetMargins(30, 15, 20, 15); - var title = new Paragraph($"รายชื่อผู้สอบแข่งขันได้\n{examName}") + var title = new Paragraph($"รายชื่อผู้สอบคัดเลือกได้\n{examName}") .SetBold() .SetMultipliedLeading(1.0f) .SetTextAlignment(TextAlignment.CENTER); @@ -924,6 +924,282 @@ namespace BMA.EHR.Report.Service.Controllers } } + /// + /// รายชื่อผู้มีสิทธิ์สอบ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือก) + /// + /// รหัสรอบการสอบ + /// + /// เมื่อแสดงรายงานสำเร็จ + /// ค่าตัวแปรที่ส่งมาไม่ถูกต้อง + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("candidate/candidate-new/{id:length(36)}")] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GetListCandidateNewReportAsync(Guid id) + { + try + { + var periodExam = await _context.PeriodExams.AsQueryable() + .Where(x => x.CheckDisability == false) + .FirstOrDefaultAsync(x => x.Id == id); + + if (periodExam == null) + return Error("ไม่พบข้อมูลการรับสมัครสอบ"); + + var data = await _context.Candidates.AsQueryable() + .Include(x => x.PeriodExam) + .ThenInclude(x => x.PositionExam) + .Where(x => x.PeriodExam!.Id == periodExam.Id) + .OrderBy(x => x.ExamIdenNumber) + .ThenBy(x => x.PositionExam!.CreatedAt) + .Select(p => new + { + FullName = $"{p.PrefixName ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}", + PositionName = p.PositionExam!.PositionName, + Remark = !string.IsNullOrEmpty(p.ExamReason) ? p.ExamReason.ToThaiNumber() : "", + ExamId = !string.IsNullOrEmpty(p.ExamIdenNumber) ? p.ExamIdenNumber.ToThaiNumber() : "", + ExamName = + ($"{p.PeriodExam!.Name} ครั้งที่ {p.PeriodExam.Round}/{p.PeriodExam.Year.Value.ToThaiYear()}").ToThaiNumber(), + }).ToListAsync(); + + if (data.Count == 0) + return Error("ไม่พบข้อมูลในระบบ"); + + var examName = data.First().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(), + ExamId = x.ExamId, + FullName = x.FullName, + Remark = x.Remark + }).ToList() + }) + .ToList(); + + // เตรียม MemoryStream + using (var stream = new MemoryStream()) + { + // สร้าง PDF document + using (var writer = new PdfWriter(stream)) + using (var pdf = new PdfDocument(writer)) + using (var document = new Document(pdf, iText.Kernel.Geom.PageSize.A4)) + { + // กำหนดฟ้อนต์ TH-Sarabun + var fontPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Fonts", "THSarabun.ttf"); + var font = PdfFontFactory.CreateFont(fontPath, "Identity-H"); + document.SetFont(font).SetFontSize(16); + + // ตั้งค่าระยะขอบ top, right, bottom, left + document.SetMargins(30, 15, 20, 15); + + // Title + var title = new Paragraph($"รายชื่อผู้มีสิทธิ์สอบ\n{examName ?? ""}") + .SetBold() + .SetMultipliedLeading(1.0f) + .SetTextAlignment(TextAlignment.CENTER); + + document.Add(title); + float[] columnWidths = { 10f, 20f, 45f, 25f }; + // Loop Groups + foreach (var group in groupData) + { + // Group Header (ตำแหน่ง) + Paragraph positionHeader = new Paragraph($"{group.PositionName} {group.Total}") + .SetBold() + .SetMultipliedLeading(1.0f) + .SetTextAlignment(TextAlignment.CENTER) + .SetMarginBottom(5); + + document.Add(positionHeader); + + var table = new iText.Layout.Element.Table(UnitValue.CreatePercentArray(columnWidths)).UseAllAvailableWidth(); + + // Table Header + string[] headers = { "ลำดับที่", "เลขประจำตัวสอบ", "ชื่อ-สกุล", "หมายเหตุ" }; + foreach (var h in headers) + { + table.AddHeaderCell(new Cell() + .Add(new Paragraph(h).SetMultipliedLeading(1.0f)) + .SetBold() + .SetTextAlignment(TextAlignment.CENTER)); + } + + // Table Details + foreach (var x in group.Persons) + { + table.AddCell(new Cell().Add(new Paragraph(x.No ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER)); + + table.AddCell(new Cell().Add(new Paragraph(x.ExamId ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER)); + + table.AddCell(new Cell().Add(new Paragraph(x.FullName ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.LEFT)); + + table.AddCell(new Cell().Add(new Paragraph(x.Remark ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER)); + } + document.Add(table); + document.Add(new Paragraph("").SetMarginBottom(15)); + } + } + return File(stream.ToArray(), "application/pdf", $"รายชื่อผู้มีสิทธิ์สอบ_{examName}"); + } + } + catch (Exception ex) + { + return Error(ex); + } + } + + /// + /// รายชื่อผู้สอบคัดเลือกได้ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบคัดเลือก) + /// + /// รหัสรอบการสอบ + /// + /// เมื่อแสดงรายงานสำเร็จ + /// ค่าตัวแปรที่ส่งมาไม่ถูกต้อง + /// ไม่ได้ Login เข้าระบบ + /// เมื่อเกิดข้อผิดพลาดในการทำงาน + [HttpGet("candidate/pass-new/{id:length(36)}")] + [AllowAnonymous] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> GetCandidatePassExamListNewReportAsync(Guid id) + { + try + { + var periodExam = await _context.PeriodExams.AsQueryable() + .Where(x => x.CheckDisability == false) + .FirstOrDefaultAsync(x => x.Id == id); + + if (periodExam == null) + return Error("ไม่พบข้อมูลการรับสมัครสอบ"); + + var candidates = await _context.Candidates.AsQueryable() + .Include(x => x.PeriodExam) + .ThenInclude(x => x.PositionExam) + .Where(x => x.PeriodExam!.Id == periodExam.Id) + .Where(x => x.Status != "register") + .OrderBy(x => x.PositionExam!.CreatedAt) + .ToListAsync(); + + var data = candidates.Select((p, idx) => new + { + PositionName = p.PositionExam!.PositionName, + FullName = $"{p.PrefixName ?? ""}{p.FirstName ?? ""} {p.LastName ?? ""}".Trim(), + ExamResult = p.Pass, + ExamName = $"{p.PeriodExam!.Name} ครั้งที่ {p.PeriodExam.Round}/{p.PeriodExam!.Year.Value.ToThaiYear()}".ToThaiNumber(), + Number = string.IsNullOrEmpty(p.Number) ? (idx + 1) : Convert.ToInt32(p.Number), + SumScore = (Convert.ToInt32(p.PointB ?? "0") + Convert.ToInt32(p.PointC ?? "0")) .ToString().ToThaiNumber(), + SeatNumber = string.IsNullOrEmpty(p.SeatNumber) ? "" : p.SeatNumber.ToThaiNumber(), + }) + .OrderBy(x => x.Number) + .Where(x => x.ExamResult?.Trim() == "ได้") + .ToList(); + + if (data.Count == 0) + return Error("ไม่พบข้อมูลในระบบ"); + + var examName = data.First().ExamName; + + // Group by PositionName + var groupData = data + .GroupBy(g => g.PositionName) + .Select(g => new + { + PositionName = $"ตำแหน่ง {g.Key}", + Total = $"จำนวน {g.Count().ToString().ToThaiNumber()} ราย", + Persons = g.Select((x) => new + { + Number = x.Number > 0 ? x.Number.ToString().ToThaiNumber() : "", + FullName = x.FullName, + SumScore = x.SumScore, + SeatNumber = x.SeatNumber + }).ToList() + }) + .ToList(); + + using (var stream = new MemoryStream()) + { + using (var writer = new PdfWriter(stream)) + using (var pdf = new PdfDocument(writer)) + using (var document = new Document(pdf, iText.Kernel.Geom.PageSize.A4)) + { + var fontPath = System.IO.Path.Combine(Environment.CurrentDirectory, "Fonts", "THSarabun.ttf"); + var font = PdfFontFactory.CreateFont(fontPath, "Identity-H"); + + document.SetFont(font).SetFontSize(16); + document.SetMargins(30, 15, 20, 15); + + var title = new Paragraph($"รายชื่อผู้สอบคัดเลือกได้\n{examName}") + .SetBold() + .SetMultipliedLeading(1.0f) + .SetTextAlignment(TextAlignment.CENTER); + + document.Add(title); + // float[] columnWidths = { 10f, 20f, 45f, 25f }; + float[] columnWidths = { 10f, 25f, 25f, 25f }; + foreach (var g in groupData) + { + // Header per group + Paragraph positionHeader = new Paragraph($"{g.PositionName} {g.Total}") + .SetBold() + .SetMultipliedLeading(1.0f) + .SetTextAlignment(TextAlignment.CENTER) + .SetMarginBottom(5); + + + document.Add(positionHeader); + + var table = new iText.Layout.Element.Table(UnitValue.CreatePercentArray(columnWidths)).UseAllAvailableWidth(); + + string[] headers = { "ลำดับที่", "สนามสอบ", "ชื่อ - นามสกุล", "คะแนนสอบ" }; + foreach (var h in headers) + { + table.AddHeaderCell(new Cell().Add(new Paragraph(h).SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER) + .SetBold()); + } + + foreach (var p in g.Persons) //SeatNumber + { + table.AddCell(new Cell().Add(new Paragraph(p.Number ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER)); + table.AddCell(new Cell().Add(new Paragraph(p.SeatNumber).SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.LEFT)); + table.AddCell(new Cell().Add(new Paragraph(p.FullName ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.LEFT)); + table.AddCell(new Cell().Add(new Paragraph(p.SumScore ?? "").SetMultipliedLeading(1.0f)) + .SetTextAlignment(TextAlignment.CENTER)); + } + + document.Add(table); + document.Add(new Paragraph("").SetMarginBottom(15)); + } + } + return File(stream.ToArray(), "application/pdf", $"รายชื่อผู้สอบแข่งขันได้_{examName}"); + } + } + catch (Exception ex) + { + return Error(ex, "เกิดข้อผิดพลาดในการแสดงรายงาน"); + } + } + #endregion } }