hrms-api-report-v1/Controllers/RecruitReportController.cs

669 lines
36 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Net.Http.Headers;
using BMA.EHR.Organization.Service.Extensions;
using BMA.EHR.Profile.Service.Controllers;
using BMA.EHR.Recruit.Service.Services;
using BMA.EHR.Report.Service.Data;
using BMA.EHR.Report.Service.Responses;
using Microsoft.AspNetCore.Mvc;
using iText.Kernel.Font;
using iText.Kernel.Pdf;
using iText.Layout.Element;
using iText.Layout.Properties;
using iText.Layout;
using iText.IO.Font;
using System.IO;
using System.Threading.Tasks;
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using Swashbuckle.AspNetCore.Annotations;
using Telerik.Reporting;
using Telerik.Reporting.Processing;
namespace BMA.EHR.Report.Service.Controllers
{
[Route("api/v{version:apiVersion}/report/recruit")]
[ApiVersion("1.0")]
[ApiController]
[Produces("application/json")]
[Authorize]
[SwaggerTag("รายงานข้อมูลการสอบแข่งขัน")]
public class RecruitReportController : BaseController
{
#region " Fields "
private readonly ApplicationDbContext _context;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly IConfiguration _configuration;
private readonly string space = "";
private readonly RecruitService _recruitService;
private readonly IHttpContextAccessor _httpContextAccessor;
#endregion
#region " Constructor and Destructor "
public RecruitReportController(ApplicationDbContext context,
IWebHostEnvironment hostingEnvironment,
IConfiguration configuration,
IHttpContextAccessor httpContextAccessor,
RecruitService recruitService)
{
this._context = context;
this._hostingEnvironment = hostingEnvironment;
this._configuration = configuration;
this._recruitService = recruitService;
this._httpContextAccessor = httpContextAccessor;
}
private string? token => _httpContextAccessor.HttpContext.Request.Headers["Authorization"];
#endregion
#region " Methods "
/// <summary>
/// แสดงหนังสือรับรอง
/// </summary>
/// <param name="id">รหัสรอบการสอบ</param>
/// <param name="examId">เลขประจำตัวผู้สมัครสอบ</param>
/// <param name="type">ชนิดของรายงาน</param>
/// <returns></returns>
/// <response code="200">เมื่อแสดงรายงานสำเร็จ</response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("certificate/{type:int}/{id:length(36)}/{examId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetCertificateReportAsync(Guid id, string examId, int type)
{
try
{
var _data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.Where(x => x.RecruitImport.Id == id)
.Where(x => x.ExamId == examId)
.FirstOrDefaultAsync();
if (_data == null)
return Error("ไม่พบข้อมูลในระบบ");
// if (_data.AuthName == null || _data.AuthName == "")
// {
// var apiUrl = $"{_configuration["API"]}/org/find/head/officer";
// using (var client = new HttpClient())
// {
// client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Replace("Bearer ", ""));
// client.DefaultRequestHeaders.Add("api_key", _configuration["API_KEY"]);
// var _req = new HttpRequestMessage(HttpMethod.Get, apiUrl);
// var _res = await client.SendAsync(_req);
// var _result = await _res.Content.ReadAsStringAsync();
// if (_res.IsSuccessStatusCode)
// {
// var org = JsonConvert.DeserializeObject<dynamic>(_result);
// _data.AuthName = org.result.name == null ? "" : org.result.name;
// _data.AuthPosition = org.result.position == null ? "" : org.result.position;
// await _context.SaveChangesAsync();
// }
// }
// }
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.Where(x => x.RecruitImport.Id == id)
.Where(x => x.ExamId == examId)
.Join(_context.RecruitScores.AsQueryable()
.Include(x => x.ScoreImport),
rc => new { rc.RecruitImport.Year, rc.ExamId },
sc => new { sc.ScoreImport.Year, sc.ExamId },
(p, sr) => new
{
ExamID = p.ExamId,
p.CitizenId,
Order = p.RecruitImport.Order,
Year = p.RecruitImport.Year.ToThaiYear(),
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
ExamResult = sr == null ? "" : sr.ExamStatus,
EndDate = p.RecruitImport.RegisterEndDate == null ? "-" : p.RecruitImport.RegisterEndDate.Value.ToThaiFullDate3(),
AuthName = p.RecruitImport.AuthName,
AuthPosition = p.RecruitImport.AuthPosition
})
.FirstOrDefaultAsync();
if (data == null)
return Error("ไม่พบข้อมูลในระบบ");
var rptFile = Path.Combine(_hostingEnvironment.ContentRootPath, "Report", "Recruit", $"rptCertificate{type}.trdp");
ReportPackager reportPackager = new ReportPackager();
Telerik.Reporting.Report report = null;
using (var sourceStream = System.IO.File.OpenRead(rptFile))
{
report = (Telerik.Reporting.Report)reportPackager.UnpackageDocument(sourceStream);
}
report.DataSource = data;
System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
InstanceReportSource instanceReportSource = new InstanceReportSource()
{
ReportDocument = report
};
ReportProcessor reportProcessor = new ReportProcessor(_configuration);
RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, deviceInfo);
var content = result.DocumentBytes;
return File(content, "application/pdf", $"หนังสือรับรอง_{data.CitizenId}_{data.FullName}.pdf");
}
catch (Exception ex)
{
return Error(ex, "เกิดข้อผิดพลาดในการแสดงรายงาน");
}
}
/// <summary>
/// แสดงเอกสารผลสอบ
/// </summary>
/// <param name="id">รหัสรอบการสอบ</param>
/// <param name="examId">เลขประจำตัวผู้สมัครสอบ</param>
/// <returns></returns>
/// <response code="200">เมื่อแสดงรายงานสำเร็จ</response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("score/{id:length(36)}/{examId}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetScoreReportAsync(Guid id, string examId)
{
try
{
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.Include(x => x.Documents)
.ThenInclude(x => x.DocumentFile)
.Where(x => x.RecruitImport.Id == id)
.Where(x => x.ExamId == examId)
.Join(_context.RecruitScores.AsQueryable()
.Include(x => x.ScoreImport),
rc => new { rc.RecruitImport.Year, rc.ExamId },
sc => new { sc.ScoreImport.Year, sc.ExamId },
(p, sr) => new
{
ExamId = p.ExamId,
CitizenId = p.CitizenId,
p.Prefix,
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
DateOfBirth = p.DateOfBirth.HasValue && p.DateOfBirth.Value != DateTime.MinValue
? p.DateOfBirth.Value.ToThaiShortDate()
: "",
Gender = p.Gendor,
Degree = p.Educations.First().Degree,
Major = p.Educations.First().Major,
ExamResult = sr == null ? "" : sr.ExamStatus,
University = p.Educations.First().University,
PositionName = p.PositionName,
ExamName = $"{p.RecruitImport.Name} ครั้งที่ {p.RecruitImport.Order}/{p.RecruitImport.Year.ToThaiYear()}",
Number = sr == null ? "" : sr.Number,
ExamCount = _recruitService.GetExamCount(p.CitizenId),
ScoreExpire = p.RecruitImport.AnnouncementDate == null ? "" : p.RecruitImport.AnnouncementDate.Value.AddYears(2).ToThaiShortDate(),
FullA = sr == null ? 0.0 : sr.FullA,
SumA = sr == null ? 0.0 : sr.SumA,
//FullB = sr == null ? 0.0 : sr.FullB,
//SumB = sr == null ? 0.0 : sr.SumB,
FullC = sr == null ? 0.0 : sr.FullC,
SumC = sr == null ? 0.0 : sr.SumC,
})
.FirstOrDefaultAsync();
var rptFile = Path.Combine(_hostingEnvironment.ContentRootPath, "Report", "Recruit", $"rptExamResult.trdp");
ReportPackager reportPackager = new ReportPackager();
Telerik.Reporting.Report report = null;
using (var sourceStream = System.IO.File.OpenRead(rptFile))
{
report = (Telerik.Reporting.Report)reportPackager.UnpackageDocument(sourceStream);
}
report.DataSource = data;
System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
InstanceReportSource instanceReportSource = new InstanceReportSource()
{
ReportDocument = report
};
ReportProcessor reportProcessor = new ReportProcessor(_configuration);
RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, deviceInfo);
var content = result.DocumentBytes;
return File(content, "application/pdf", $"ผลคะแนนสอบ_{data.CitizenId}_{data.FullName}.pdf");
}
catch (Exception ex)
{
return Error(ex, "เกิดข้อผิดพลาดในการแสดงรายงาน");
}
}
[HttpGet("candidate/{id:length(36)}")]
[AllowAnonymous]
public async Task<ActionResult<ResponseObject>> GetCandidateListReportAsync(Guid id)
{
try
{
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.Include(x => x.Documents)
.ThenInclude(x => x.DocumentFile)
.Where(x => x.RecruitImport.Id == id)
.OrderBy(x => x.ExamId)
.Select(p => new
{
ExamId = p.ExamId != null ? p.ExamId.ToThaiNumber() : string.Empty,
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
PositionName = p.PositionName,
ExamName =
$"ครั้งที่ {(p.RecruitImport != null ? p.RecruitImport.Order.ToString().ToThaiNumber() : "")}/{(p.RecruitImport != null ? p.RecruitImport.Year.ToThaiYear().ToString().ToThaiNumber() : "")}",
}).ToListAsync();
if (data.Count == 0) return Error("ไม่พบข้อมูลในระบบ");
//var rptFile = Path.Combine(_hostingEnvironment.ContentRootPath, "Report", "Recruit", $"rptCandidateList.trdp");
//ReportPackager reportPackager = new ReportPackager();
//Telerik.Reporting.Report report = null;
//using (var sourceStream = System.IO.File.OpenRead(rptFile))
//{
// report = (Telerik.Reporting.Report)reportPackager.UnpackageDocument(sourceStream);
//}
////report.DataSource = data;
//report.ReportParameters["ExamName"].Value = data[0].ExamName.ToThaiNumber();
//var tbl = (Telerik.Reporting.Table)report.Items["detailSection1"].Items["table1"];
//tbl.DataSource = data;
//System.Collections.Hashtable deviceInfo = new System.Collections.Hashtable();
//InstanceReportSource instanceReportSource = new InstanceReportSource()
//{
// ReportDocument = report
//};
//ReportProcessor reportProcessor = new ReportProcessor(_configuration);
//RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, deviceInfo);
//var content = result.DocumentBytes;
//return File(content, "application/pdf", $"รายชื่อผู้มีสิทธิ์สอบ_{data.First().ExamName}.pdf");
var examName = data[0].ExamName;
var _data = new
{
template = "rptCandidateList",
reportName = $"รายชื่อผู้มีสิทธิ์สอบ_{data.First().ExamName}",
data = new
{
examName = examName,
data = data
}
};
return Success(_data);
}
catch (Exception ex)
{
return Error(ex);
}
}
/// <summary>
/// รายชื่อผู้มีสิทธิ์สอบ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบแข่งขัน)
/// </summary>
/// <param name="id">รหัสรอบการสอบ</param>
/// <returns></returns>
/// <response code="200">เมื่อแสดงรายงานสำเร็จ</response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("candidate-new/{id:length(36)}")]
[AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetCandidateNewListReportAsync(Guid id)
{
try
{
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 = !string.IsNullOrEmpty(p.Remark) ? p.Remark.ToThaiNumber() : "",
ExamId = !string.IsNullOrEmpty(p.ExamId) ? p.ExamId.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 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(
$"รายชื่อผู้ชำระค่าธรรมเนียมการสมัครสอบการแข่งขันเพื่อบรรจุและแต่งตั้งบุคคลเข้ารับราชการเป็นข้าราชการกรุงเทพมหานครสามัญ {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);
// เว้นระหว่าง groups
document.Add(new Paragraph("").SetMarginBottom(15));
}
}
return File(stream.ToArray(), "application/pdf", $"รายชื่อผู้มีสิทธิ์สอบ_{examName}");
}
}
catch (Exception ex)
{
return Error(ex);
}
}
[HttpGet("pass/{id:length(36)}")]
[AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetPassExamListReportAsync(Guid id)
{
try
{
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.ThenInclude(x => x.ScoreImport)
.Include(x => x.Documents)
.ThenInclude(x => x.DocumentFile)
.Join(_context.RecruitScores.AsQueryable()
.Include(x => x.ScoreImport)
.Where(x => x.ScoreImport.RecruitImportId == id)
.Where(x => x.ExamStatus == "ผ่าน"),
rc => new { id = rc.RecruitImport.Id, examId = rc.ExamId },
sc => new { id = sc.ScoreImport.RecruitImportId, examId = sc.ExamId },
(p, sr) => new
{
Id = p.RecruitImport.Id,
ExamId = p.ExamId != null ? p.ExamId.ToThaiNumber() : string.Empty,
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
ExamResult = sr == null ? "" : sr.ExamStatus,
ExamName = p.RecruitImport.Order == null
? ""
: $"{p.RecruitImport.Name} ครั้งที่ {p.RecruitImport.Order.ToString().ToThaiNumber()}/{p.RecruitImport.Year.ToThaiYear().ToString().ToThaiNumber()}",
Number = sr == null || sr.Number == null ? 0 : Convert.ToInt32(sr.Number),
SumScore = sr == null
? ""
: (((sr.SumA > 0 ? sr.SumA : 0) + (sr.SumB > 0 ? sr.SumB : 0) + (sr.SumC > 0 ? sr.SumC : 0)).ToString()).ToThaiNumber(),
})
.OrderBy(x => x.Number)
.Where(x => x.Id == id)
.Where(x => x.ExamResult == "ผ่าน")
.ToListAsync();
if (data.Count == 0)
return Error("ไม่พบข้อมูลในระบบ");
var data_ = data.Select(x => new
{
x.ExamName,
Number = x.Number.ToString().ToThaiNumber(),
x.ExamId,
x.FullName,
x.SumScore
}).ToList();
var examName = data[0].ExamName;
var _data = new
{
template = "rptPassExamList",
reportName = $"รายชื่อผู้สอบแข่งขันได้_{data.First().ExamName}",
data = new
{
examName = examName,
data = data_
}
};
return Success(_data);
}
catch (Exception ex)
{
return Error(ex, "เกิดข้อผิดพลาดในการแสดงรายงาน");
}
}
/// <summary>
/// รายชื่อผู้สอบแข่งขันได้ แสดงรายชื่อแบ่งตามตำแหน่ง (สอบแข่งขัน)
/// </summary>
/// <param name="id">รหัสรอบการสอบ</param>
/// <returns></returns>
/// <response code="200">เมื่อแสดงรายงานสำเร็จ</response>
/// <response code="400">ค่าตัวแปรที่ส่งมาไม่ถูกต้อง</response>
/// <response code="401">ไม่ได้ Login เข้าระบบ</response>
/// <response code="500">เมื่อเกิดข้อผิดพลาดในการทำงาน</response>
[HttpGet("pass-new/{id:length(36)}")]
[AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<ResponseObject>> GetPassExamNewListReportAsync(Guid id)
{
try
{
var data = await _context.Recruits.AsQueryable()
.Include(x => x.RecruitImport)
.ThenInclude(x => x.ScoreImport)
.Join(_context.RecruitScores.AsQueryable()
.Include(x => x.ScoreImport)
.Where(x => x.ScoreImport.RecruitImportId == id)
.Where(x => x.ExamStatus == "ผ่าน"),
rc => new { id = rc.RecruitImport.Id, examId = rc.ExamId },
sc => new { id = sc.ScoreImport.RecruitImportId, examId = sc.ExamId },
(p, sr) => new
{
PositionName = p.PositionName,
FullName = $"{p.Prefix}{p.FirstName} {p.LastName}",
ExamResult = sr == null ? "" : sr.ExamStatus,
ExamName = p.RecruitImport.Order == null
? ""
: $"{p.RecruitImport.Name} ครั้งที่ {p.RecruitImport.Order.ToString().ToThaiNumber()}/{p.RecruitImport.Year.ToThaiYear().ToString().ToThaiNumber()}",
Number = sr == null || sr.Number == null ? 0 : Convert.ToInt32(sr.Number),
SumScore = sr == null
? ""
: (((decimal)(sr.SumA > 0 ? sr.SumA : 0) + (sr.SumB > 0 ? sr.SumB : 0) + (sr.SumC > 0 ? sr.SumC : 0)).ToString("0.00")).ToThaiNumber(),
})
.OrderBy(x => x.Number)
.Where(x => x.ExamResult == "ผ่าน")
.ToListAsync();
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
}).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}")
.SetMultipliedLeading(1.0f)
.SetBold()
.SetTextAlignment(TextAlignment.CENTER);
document.Add(title);
float[] columnWidths = { 10f, 20f, 45f, 25f };
foreach (var g in groupData)
{
// Header per group
Paragraph positionHeader = new Paragraph($"{g.PositionName} {g.Total}")
.SetMultipliedLeading(1.0f)
.SetTextAlignment(TextAlignment.CENTER)
.SetBold()
.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)
{
table.AddCell(new Cell().Add(new Paragraph(p.Number ?? "").SetMultipliedLeading(1.0f))
.SetTextAlignment(TextAlignment.CENTER));
table.AddCell(new Cell());
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
}
}