using System.Security.Claims; using System.Text.Json; using BMA.EHR.Recurit.Exam.Service.Core; using BMA.EHR.Recurit.Exam.Service.Data; using BMA.EHR.Recurit.Exam.Service.Models; using BMA.EHR.Recurit.Exam.Service.Request; using BMA.EHR.Recurit.Exam.Service.Response; using Microsoft.EntityFrameworkCore; using Newtonsoft.Json.Linq; using OfficeOpenXml; namespace BMA.EHR.Recurit.Exam.Service.Services { public class PeriodExamService { #region " Fields " private readonly ApplicationDbContext _context; private readonly IHttpContextAccessor _httpContextAccessor; #endregion #region " Constructor and Destructor " public PeriodExamService(ApplicationDbContext context, IHttpContextAccessor httpContextAccessor) { _context = context; _httpContextAccessor = httpContextAccessor; } #endregion #region " Properties " private string? UserId => _httpContextAccessor?.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value; private string? FullName => _httpContextAccessor?.HttpContext?.User?.FindFirst("name")?.Value; #endregion #region " Methods " public async Task> GetsAsync(bool showAll = true) { if (showAll) return await _context.PeriodExams.AsQueryable() .Include(x => x.PositionExam) .Include(x => x.BankExam) .OrderBy(d => d.Name) .ToListAsync(); else return await _context.PeriodExams.AsQueryable() .Include(x => x.PositionExam) .Include(x => x.BankExam) .Where(p => p.IsActive) .OrderBy(d => d.Name) .Select(x => new PeriodExam { AnnouncementEndDate = x.AnnouncementEndDate, AnnouncementStartDate = x.AnnouncementStartDate, CheckDisability = x.CheckDisability, CheckDocument = x.CheckDocument, Detail = x.Detail, Fee = x.Fee, Id = x.Id, IsActive = x.IsActive, Name = x.Name, Note = x.Note, OrganizationCodeId = x.OrganizationCodeId, OrganizationCodeName = x.OrganizationCodeName, OrganizationId = x.OrganizationId, OrganizationName = x.OrganizationName, PaymentEndDate = x.PaymentEndDate, PaymentKrungThai = x.PaymentKrungThai, PaymentStartDate = x.PaymentStartDate, RegisterEndDate = x.RegisterEndDate, RegisterStartDate = x.RegisterStartDate, Round = x.Round, SetSeat = x.SetSeat, Year = x.Year, BankExam = x.BankExam.OrderBy(o => o.CreatedAt).Select(b => new BankExam { Id = b.Id, AccountName = b.AccountName, AccountNumber = b.AccountNumber, BankName = b.BankName, }).ToList(), PositionExam = x.PositionExam.OrderBy(o => o.CreatedAt).Select(b => new PositionExam { Id = b.Id, TypeId = b.TypeId, TypeName = b.TypeName, PositionId = b.PositionId, PositionName = b.PositionName, }).ToList(), }) .ToListAsync(); } public async Task GetsExamAndCandidateAsync(string examId, bool showAll = true) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); return periodExam; } public async Task GetsStatusPaymentAsync(string examId, bool showAll = true) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); return new RequestStatusExam { Name = periodExam.Name, Status = DateTime.Now > periodExam.PaymentEndDate, SetSeat = periodExam.SetSeat, }; } public async Task GetsNamePositionAsync(string examId, string positionId) { var periodExam = await _context.PeriodExams.AsQueryable() .Include(x => x.PositionExam) .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); if (positionId != "00000000-0000-0000-0000-000000000000") { return new RequestPositionName { Name = periodExam.Name, Posiiton = periodExam.PositionExam.FirstOrDefault(x => x.Id == Guid.Parse(positionId) && x.PeriodExam == periodExam), }; } else { return new RequestPositionName { Name = periodExam.Name, Posiiton = null, }; } } public async Task CreateAsync(RequestPeriodExam inserted) { var periodExam = new PeriodExam { Name = inserted.Name, CheckDocument = inserted.CheckDocument, CheckDisability = inserted.CheckDisability, Round = inserted.Round, Year = inserted.Year, Fee = inserted.Fee, RegisterStartDate = inserted.RegisterStartDate, RegisterEndDate = inserted.RegisterEndDate, PaymentStartDate = inserted.PaymentStartDate, PaymentEndDate = inserted.PaymentEndDate, AnnouncementStartDate = inserted.AnnouncementStartDate, AnnouncementEndDate = inserted.AnnouncementEndDate, OrganizationCodeId = inserted.OrganizationCodeId, OrganizationCodeName = inserted.OrganizationCodeName, OrganizationId = inserted.OrganizationId, OrganizationName = inserted.OrganizationName, PaymentKrungThai = inserted.PaymentKrungThai, Detail = inserted.Detail, Note = inserted.Note, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", LastUpdatedAt = DateTime.Now, LastUpdateUserId = UserId ?? "", CreatedFullName = FullName ?? "", LastUpdateFullName = FullName ?? "", }; foreach (var bank in inserted.BankExam) { var bankExam = new BankExam { PeriodExam = periodExam, AccountName = bank.AccountName, AccountNumber = bank.AccountNumber, BankName = bank.BankName, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", LastUpdatedAt = DateTime.Now, LastUpdateUserId = UserId ?? "", CreatedFullName = FullName ?? "", LastUpdateFullName = FullName ?? "", }; await _context.BankExams.AddAsync(bankExam); } foreach (var position in inserted.PositionExam) { var positionExam = new PositionExam { PeriodExam = periodExam, PositionId = position.PositionId, PositionName = position.PositionName, TypeId = position.TypeId, TypeName = position.TypeName, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", LastUpdatedAt = DateTime.Now, LastUpdateUserId = UserId ?? "", CreatedFullName = FullName ?? "", LastUpdateFullName = FullName ?? "", }; await _context.PositionExams.AddAsync(positionExam); } await _context.PeriodExams.AddAsync(periodExam); await _context.SaveChangesAsync(); } public async Task UpdateAsync(string examId, RequestPeriodExam updated) { var periodExam = await _context.PeriodExams.AsQueryable() .Include(x => x.BankExam) .Include(x => x.PositionExam) .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); periodExam.Name = updated.Name; periodExam.CheckDocument = updated.CheckDocument; periodExam.CheckDisability = updated.CheckDisability; periodExam.Round = updated.Round; periodExam.Year = updated.Year; periodExam.Fee = updated.Fee; periodExam.RegisterStartDate = updated.RegisterStartDate; periodExam.RegisterEndDate = updated.RegisterEndDate; periodExam.PaymentStartDate = updated.PaymentStartDate; periodExam.PaymentEndDate = updated.PaymentEndDate; periodExam.AnnouncementStartDate = updated.AnnouncementStartDate; periodExam.AnnouncementEndDate = updated.AnnouncementEndDate; periodExam.OrganizationCodeId = updated.OrganizationCodeId; periodExam.OrganizationCodeName = updated.OrganizationCodeName; periodExam.OrganizationId = updated.OrganizationId; periodExam.OrganizationName = updated.OrganizationName; periodExam.PaymentKrungThai = updated.PaymentKrungThai; periodExam.Detail = updated.Detail; periodExam.Note = updated.Note; periodExam.LastUpdatedAt = DateTime.Now; periodExam.LastUpdateUserId = UserId ?? ""; periodExam.LastUpdateFullName = FullName ?? ""; foreach (var bank in periodExam.BankExam) { var bankData = updated.BankExam .FirstOrDefault(x => x.Id == bank.Id); if (bankData != null) { bank.AccountName = bankData.AccountName; bank.AccountNumber = bankData.AccountNumber; bank.BankName = bankData.BankName; bank.LastUpdatedAt = DateTime.Now; bank.LastUpdateUserId = UserId ?? ""; bank.LastUpdateFullName = FullName ?? ""; } else { var bankDelete = await _context.BankExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == bank.Id); if (bankDelete != null) _context.BankExams.Remove(bankDelete); } } foreach (var position in periodExam.PositionExam) { var positionData = updated.PositionExam .FirstOrDefault(x => x.Id == position.Id); if (positionData != null) { position.PositionId = positionData.PositionId; position.PositionName = positionData.PositionName; position.TypeId = positionData.TypeId; position.TypeName = positionData.TypeName; position.LastUpdatedAt = DateTime.Now; position.LastUpdateUserId = UserId ?? ""; position.LastUpdateFullName = FullName ?? ""; } else { var positionDelete = await _context.PositionExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == position.Id); if (positionDelete != null) _context.PositionExams.Remove(positionDelete); } } var bankAdd = updated.BankExam .Where(x => x.Id == Guid.Parse("00000000-0000-0000-0000-000000000000")) .ToList(); foreach (var bank in bankAdd) { var bankExam = new BankExam { PeriodExam = periodExam, AccountName = bank.AccountName, AccountNumber = bank.AccountNumber, BankName = bank.BankName, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", LastUpdatedAt = DateTime.Now, LastUpdateUserId = UserId ?? "", CreatedFullName = FullName ?? "", LastUpdateFullName = FullName ?? "", }; await _context.BankExams.AddAsync(bankExam); } var positionAdd = updated.PositionExam .Where(x => x.Id == Guid.Parse("00000000-0000-0000-0000-000000000000")) .ToList(); foreach (var position in positionAdd) { var positionExam = new PositionExam { PeriodExam = periodExam, PositionId = position.PositionId, PositionName = position.PositionName, TypeId = position.TypeId, TypeName = position.TypeName, CreatedAt = DateTime.Now, CreatedUserId = UserId ?? "", LastUpdatedAt = DateTime.Now, LastUpdateUserId = UserId ?? "", CreatedFullName = FullName ?? "", LastUpdateFullName = FullName ?? "", }; await _context.PositionExams.AddAsync(positionExam); } await _context.SaveChangesAsync(); } public async Task DeleteAsync(string examId) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); _context.PeriodExams.Remove(periodExam); await _context.SaveChangesAsync(); } public async Task> GetsCandidateByStatusAsync(string examId, string status) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); if (status == "all") { return await _context.Candidates.AsQueryable() .Where(x => x.PeriodExam == periodExam && x.Status != "register" && x.Status != "rejectRegister") .ToListAsync(); } else { return await _context.Candidates.AsQueryable() .Where(x => x.PeriodExam == periodExam && x.Status == status) .ToListAsync(); } } public async Task GetsAsyncInformation(string candidateId) { return await _context.Candidates.AsQueryable() .Where(x => x.Id == Guid.Parse(candidateId)) .Select(x => new CandidateInformationResponseItem { Prefix = x.Prefix, PrefixId = x.Prefix != null ? x.Prefix.Id.ToString() : null, FirstName = x.FirstName, LastName = x.LastName, Nationality = x.Nationality, DateOfBirth = x.DateOfBirth, Relationship = x.Relationship, RelationshipId = x.Relationship != null ? x.Relationship.Id.ToString() : null, CitizenProvince = x.CitizenProvince, CitizenProvinceId = x.CitizenProvince != null ? x.CitizenProvince.Id.ToString() : null, CitizenDistrict = x.CitizenDistrict, CitizenDistrictId = x.CitizenDistrict != null ? x.CitizenDistrict.Id.ToString() : null, CitizenDate = x.CitizenDate, Email = x.Email, CitizenId = x.CitizenId, Telephone = x.Telephone, MobilePhone = x.MobilePhone, Knowledge = x.Knowledge, }) .FirstOrDefaultAsync(); } public async Task GetsAsyncOccupation(string candidateId) { return await _context.Candidates.AsQueryable() .Where(x => x.Id == Guid.Parse(candidateId)) .Select(x => new CandidateOccupationResponseItem { OccupationType = x.OccupationType, OccupationCompany = x.OccupationCompany, OccupationDepartment = x.OccupationDepartment, OccupationEmail = x.OccupationEmail, OccupationTelephone = x.OccupationTelephone, OccupationPosition = x.OccupationPosition, }) .FirstOrDefaultAsync(); } public async Task GetsAsyncAddress(string candidateId) { return await _context.Candidates.AsQueryable() .Where(x => x.Id == Guid.Parse(candidateId)) .Select(x => new CandidateAddressResponseItem { RegistAddress = x.RegistAddress, RegistProvince = x.RegistProvince, RegistProvinceId = x.RegistProvince != null ? x.RegistProvince.Id.ToString() : null, RegistDistrict = x.RegistDistrict, RegistDistrictId = x.RegistDistrict != null ? x.RegistDistrict.Id.ToString() : null, RegistSubDistrict = x.RegistSubDistrict, RegistSubDistrictId = x.RegistSubDistrict != null ? x.RegistSubDistrict.Id.ToString() : null, RegistZipCode = x.RegistZipCode, RegistSame = x.RegistSame, CurrentAddress = x.CurrentAddress, CurrentProvince = x.CurrentProvince, CurrentProvinceId = x.CurrentProvince != null ? x.CurrentProvince.Id.ToString() : null, CurrentDistrict = x.CurrentDistrict, CurrentDistrictId = x.CurrentDistrict != null ? x.CurrentDistrict.Id.ToString() : null, CurrentSubDistrict = x.CurrentSubDistrict, CurrentSubDistrictId = x.CurrentSubDistrict != null ? x.CurrentSubDistrict.Id.ToString() : null, CurrentZipCode = x.CurrentZipCode, }) .FirstOrDefaultAsync(); } public async Task GetsAsyncFamily(string candidateId) { return await _context.Candidates.AsQueryable() .Where(x => x.Id == Guid.Parse(candidateId)) .Select(x => new CandidateFamilyResponseItem { Marry = x.Marry, MarryPrefix = x.MarryPrefix, MarryPrefixId = x.MarryPrefix != null ? x.MarryPrefix.Id.ToString() : null, MarryFirstName = x.MarryFirstName, MarryLastName = x.MarryLastName, MarryOccupation = x.MarryOccupation, MarryNationality = x.MarryNationality, FatherPrefix = x.FatherPrefix, FatherPrefixId = x.FatherPrefix != null ? x.FatherPrefix.Id.ToString() : null, FatherFirstName = x.FatherFirstName, FatherLastName = x.FatherLastName, FatherOccupation = x.FatherOccupation, FatherNationality = x.FatherNationality, MotherPrefix = x.MotherPrefix, MotherPrefixId = x.MotherPrefix != null ? x.MotherPrefix.Id.ToString() : null, MotherFirstName = x.MotherFirstName, MotherLastName = x.MotherLastName, MotherOccupation = x.MotherOccupation, MotherNationality = x.MotherNationality, }) .FirstOrDefaultAsync(); } public async Task> GetsAsyncEducation(string candidateId) { return await _context.Educations.AsQueryable() .Include(x => x.EducationLevel) .Where(x => x.Id == Guid.Parse(candidateId)) .OrderBy(d => d.DurationStart) .ToListAsync(); } public async Task> GetsAsyncCareer(string candidateId) { return await _context.Careers.AsQueryable() .Where(x => x.Id == Guid.Parse(candidateId)) .OrderBy(d => d.DurationStart) .ToListAsync(); } private async Task> ReadExcelCandidate(IFormFile formFile) { var list = new List(); using (var stream = new MemoryStream()) { await formFile.CopyToAsync(stream); using (var package = new ExcelPackage(stream)) { for (int i = 0; i < package.Workbook.Worksheets.Count(); i++) { ExcelWorksheet worksheet = package.Workbook.Worksheets[i]; var rowCount = worksheet.Dimension.Rows; for (int row = 2; row <= rowCount; row++) { System.Diagnostics.Debug.WriteLine(worksheet); if (worksheet.Cells[row, 1].Value != null) { list.Add(new RequestImportSeat { CitizenId = worksheet.Cells[row, 1].Value != null ? worksheet.Cells[row, 1].Value.ToString() : "-", ExamIdenNumber = worksheet.Cells[row, 2].Value != null ? worksheet.Cells[row, 2].Value.ToString() : "-", SeatNumber = worksheet.Cells[row, 3].Value != null ? worksheet.Cells[row, 3].Value.ToString() : "-", Point = worksheet.Cells[row, 4].Value != null ? worksheet.Cells[row, 4].Value.ToString() : "-", }); } } } } } return list; } public async Task UploadSeatCandidateAsync(string examId, IFormFile excels) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); var candidates = await _context.Candidates .AsQueryable() .Where(x => x.PeriodExam == periodExam) .ToListAsync(); var items = await ReadExcelCandidate(excels); foreach (var candidate in candidates) { var item = items.FirstOrDefault(x => x.CitizenId == candidate.CitizenId && x.ExamIdenNumber == candidate.ExamIdenNumber); if (item != null) { if (candidate.Status == "checkSeat") { candidate.SeatNumber = item.SeatNumber; candidate.Status = "checkPoint"; } else { candidate.Status = "waiver"; } } else { candidate.Status = "waiver"; } periodExam.SetSeat = true; } await _context.SaveChangesAsync(); } public async Task UploadPointCandidateAsync(string examId, IFormFile excels) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); var candidates = await _context.Candidates .AsQueryable() .Where(x => x.PeriodExam == periodExam) .ToListAsync(); var items = await ReadExcelCandidate(excels); foreach (var candidate in candidates) { var item = items.FirstOrDefault(x => x.CitizenId == candidate.CitizenId && x.ExamIdenNumber == candidate.ExamIdenNumber); if (item != null) { if (candidate.Status == "checkPoint" || candidate.Status == "done") { candidate.Point = item.Point; candidate.Status = "done"; } else { candidate.Status = "waiver"; } } else { candidate.Status = "waiver"; } periodExam.SetSeat = true; } await _context.SaveChangesAsync(); } public async Task DownloadCandidateAsync(string examId) { var periodExam = await _context.PeriodExams.AsQueryable() .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); var candidates = await _context.Candidates .AsQueryable() .Where(x => x.PeriodExam == periodExam) .ToListAsync(); var stream = new MemoryStream(); using (var package = new ExcelPackage(stream)) { var summarySheet = package.Workbook.Worksheets.Add("Candidate"); summarySheet.TabColor = System.Drawing.Color.Black; // summarySheet.DefaultRowHeight = 17; summarySheet.Row(1).Style.Font.Bold = true; summarySheet.Cells[1, 1].Value = "เลขบัตรประชาชน"; summarySheet.Cells[1, 2].Value = "เลขประจำตัวสอบ"; summarySheet.Cells[1, 3].Value = "เลขที่นั่งสอบ"; summarySheet.Cells[1, 4].Value = "คะแนน"; int row = 2; foreach (var item in candidates) { summarySheet.Cells[row, 1].Value = item.CitizenId; summarySheet.Cells[row, 2].Value = item.ExamIdenNumber; summarySheet.Cells[row, 3].Value = item.SeatNumber; summarySheet.Cells[row, 4].Value = item.Point; row++; } summarySheet.Cells[summarySheet.Dimension.Address].AutoFitColumns(); package.Save(); } stream.Position = 0; return stream; } public async Task> GetsPaymentExamAsync(string examId) { var periodExam = await _context.PeriodExams.AsQueryable() .Include(x => x.BankExam) .FirstOrDefaultAsync(x => x.Id == Guid.Parse(examId)); if (periodExam == null) throw new Exception(GlobalMessages.ExamNotFound); return periodExam.BankExam; } #endregion } }