| @@ -54,5 +54,33 @@ namespace Diligent.WebAPI.Business.Helper | |||
| "</a>" + | |||
| "</div>"; | |||
| } | |||
| public static string SuccessfulStep(string message, string pattern, string date) | |||
| { | |||
| return "<div style=\"font-family: sans-serif\">" + | |||
| "<div style=\"font-family: sans-serif; text-align: center; \">" + | |||
| "<h2 style=\"color: #017397;\">" + pattern + "</h2>" + | |||
| "</div>" + | |||
| "<div style=\"padding: 0.25rem 2rem 0 2rem\">" + | |||
| "<p style=\"color: #017397;\">Poštovani,</p >" + | |||
| "</div>" + | |||
| "<div style=\"padding: 0 13rem 0 4rem; \">" + | |||
| "<p style=\"color: #017397;\">" + message + " " + date + "</p>" + | |||
| "</div>" + "<div style=\"padding: 0 2rem; \">" + | |||
| "<p style=\"color: #017397;\">Srdačan pozdrav,<br>Diligent HR Team</p>" + | |||
| "</div>" + | |||
| "</div>"; | |||
| } | |||
| //public static string ScheduleInterview(string pattern, string message) | |||
| //{ | |||
| // Dictionary<string, string> Patterns = new Dictionary<string, string> | |||
| // { | |||
| // { "Neuspesan korak", $"<div><p>Neuspesan korak: {message}</p></div>" }, | |||
| // { "Uspesan korak", SuccessfulStep(message, pattern) } | |||
| // }; | |||
| // return Patterns[pattern]; | |||
| //} | |||
| } | |||
| } | |||
| @@ -10,6 +10,7 @@ namespace Diligent.WebAPI.Business.MappingProfiles | |||
| CreateMap<Applicant, ApplicantViewDto>(); | |||
| CreateMap<Applicant, AdApplicantViewDto>(); | |||
| CreateMap<Applicant, ApplicantScheduleViewDto>(); | |||
| CreateMap<Applicant, PatternApplicantViewDto>(); | |||
| #endregion | |||
| #region DTOs to Models | |||
| @@ -9,6 +9,7 @@ namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<SelectionProcessCreateDto, SelectionProcess>(); | |||
| CreateMap<SelectionProcessUpdateStatusDto, SelectionProcess>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| @@ -15,8 +15,12 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task<List<PatternResponseDto>> GetFilteredPatternsAsync(FilterPatternDto filterPatternDto); | |||
| Task<List<PatternApplicantViewDto>> GetCorrespondingPatternApplicants(int id); | |||
| Task CreateAsync(PatternCreateDto patternCreateDto); | |||
| Task<ScheduleInterviewResponseDto?> ScheduleIntrviewAsync(ScheduleInterviewDto scheduleInterviewDto); | |||
| Task UpdateAsync(PatternUpdateDto patternUpdateDto, int id); | |||
| Task DeleteAsync(int id); | |||
| @@ -9,6 +9,6 @@ namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| Task<List<SelectionProcessResposneDto>> GetAllAsync(); | |||
| Task<bool> FinishSelectionProcess(SelectionProcessCreateDto model); | |||
| Task<List<SelectionLevelInfoDto>> GetCountByLevels(List<string> statuses); | |||
| Task UpdateSelectionProcessStatusAsync(int id, SelectionProcessUpdateStatusDto selectionProcessUpdateStatusDto); | |||
| } | |||
| } | |||
| @@ -13,13 +13,17 @@ namespace Diligent.WebAPI.Business.Services | |||
| private readonly IMapper _mapper; | |||
| private readonly ISelectionLevelService _selectionLevelService; | |||
| private readonly ILogger<PatternService> _logger; | |||
| private readonly IEmailer _emailer; | |||
| private readonly ISelectionProcessService _selectionProcessService; | |||
| public PatternService(DatabaseContext context, IMapper mapper, ISelectionLevelService selectionLevelService, ILogger<PatternService> logger) | |||
| public PatternService(DatabaseContext context, IMapper mapper, ISelectionLevelService selectionLevelService, ILogger<PatternService> logger, IEmailer emailer, ISelectionProcessService selectionProcessService) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _selectionLevelService = selectionLevelService; | |||
| _logger = logger; | |||
| _emailer = emailer; | |||
| _selectionProcessService = selectionProcessService; | |||
| } | |||
| public async Task<List<PatternResponseDto>> GetAllAsync() | |||
| @@ -64,6 +68,27 @@ namespace Diligent.WebAPI.Business.Services | |||
| return result; | |||
| } | |||
| public async Task<List<PatternApplicantViewDto>> GetCorrespondingPatternApplicants(int id) | |||
| { | |||
| _logger.LogInformation($"Start getting corresponding pattern applicants"); | |||
| _logger.LogInformation($"Getting pattern from database by id"); | |||
| var pattern = await _context.Patterns.Include(x => x.SelectionLevel).ThenInclude(y => y.SelectionProcesses).ThenInclude(z => z.Applicant).Where(x => x.Id == id).FirstOrDefaultAsync(); | |||
| if(pattern == null) | |||
| { | |||
| _logger.LogError($"Pattern with id = {id} not found"); | |||
| throw new EntityNotFoundException("Pattern not found"); | |||
| } | |||
| _logger.LogInformation($"Select applicants from selection processes with status \"Čeka na zakazivanje\""); | |||
| var selectionProcessesApplicants = pattern.SelectionLevel.SelectionProcesses.Where(x => x.Status == "Čeka na zakazivanje").Select(x => x.Applicant).ToList(); | |||
| _logger.LogInformation($"Mapping Pattern applicants"); | |||
| var applicants = _mapper.Map<List<PatternApplicantViewDto>>(selectionProcessesApplicants); | |||
| _logger.LogInformation($"Pattern applicants mapped successfully"); | |||
| return applicants; | |||
| } | |||
| public async Task CreateAsync(PatternCreateDto patternCreateDto) | |||
| { | |||
| _logger.LogInformation($"Start creating Pattern"); | |||
| @@ -103,6 +128,60 @@ namespace Diligent.WebAPI.Business.Services | |||
| await result; | |||
| } | |||
| public async Task<ScheduleInterviewResponseDto?> ScheduleIntrviewAsync(ScheduleInterviewDto scheduleInterviewDto) | |||
| { | |||
| _logger.LogInformation($"Start scheduling interview"); | |||
| List<string> NotSentEmails = new(); | |||
| _logger.LogInformation("Getting pattern from DB by id"); | |||
| var pattern = await _context.Patterns.Include(x => x.SelectionLevel).ThenInclude(y => y.SelectionProcesses).ThenInclude(z => z.Applicant).Where(x => x.Id == scheduleInterviewDto.PatternId).FirstOrDefaultAsync(); | |||
| if (pattern == null) | |||
| { | |||
| _logger.LogError($"Pattern with id = {scheduleInterviewDto.PatternId} not found"); | |||
| throw new EntityNotFoundException("Pattern not found"); | |||
| } | |||
| _logger.LogInformation("Pattern found in DB"); | |||
| for (int i = 0; i < scheduleInterviewDto.Emails.Count; i++) | |||
| { | |||
| var to = new List<string> { scheduleInterviewDto.Emails[i] }; | |||
| _logger.LogInformation("Select process where status is \"Čeka na zakazivanje\""); | |||
| var selectionProcesses = pattern.SelectionLevel.SelectionProcesses.Where(x => x.Status == "Čeka na zakazivanje" && x.Applicant.Email == scheduleInterviewDto.Emails[i]).FirstOrDefault(); | |||
| if(selectionProcesses != null) | |||
| { | |||
| _logger.LogInformation("Selection process is not null"); | |||
| _logger.LogInformation("Selection process status changing to \"Zakazan\""); | |||
| await _selectionProcessService.UpdateSelectionProcessStatusAsync(selectionProcesses.Id, new SelectionProcessUpdateStatusDto | |||
| { | |||
| Status = "Zakazan" | |||
| }); | |||
| _logger.LogInformation("Sending pattern to selected emails on frontend"); | |||
| await _emailer.SendEmailAsync(to, "Schedule interview", | |||
| HTMLHelper.SuccessfulStep(pattern.Message, pattern.Title, String.Format("{0:M/d/yyyy}", selectionProcesses.Date)), isHtml: true); | |||
| } | |||
| else | |||
| { | |||
| _logger.LogInformation("Selection process not found in database"); | |||
| NotSentEmails.Add(scheduleInterviewDto.Emails[i] + " ne postoji u bazi sa statusom \"Čeka na zakazivanje\" "); | |||
| continue; | |||
| } | |||
| } | |||
| if(NotSentEmails.Count() > 0) | |||
| { | |||
| _logger.LogInformation("List of not set emails are not empty"); | |||
| _logger.LogInformation("Returning list of not sent emails"); | |||
| return new ScheduleInterviewResponseDto { NotSentEmails = NotSentEmails }; | |||
| } | |||
| _logger.LogInformation("List of not sent email is empty. Return null..."); | |||
| return null; | |||
| } | |||
| public async Task UpdateAsync(PatternUpdateDto patternUpdateDto, int id) | |||
| { | |||
| _logger.LogInformation($"Start updating Pattern"); | |||
| @@ -82,5 +82,27 @@ namespace Diligent.WebAPI.Business.Services | |||
| return resMapped; | |||
| } | |||
| public async Task UpdateSelectionProcessStatusAsync(int id, SelectionProcessUpdateStatusDto selectionProcessUpdateStatusDto) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var selectionProcess = await _context.SelectionProcesses.FindAsync(id); | |||
| if (selectionProcess is null) | |||
| { | |||
| _logger.LogError($"Selection process with id = {id} not found"); | |||
| throw new EntityNotFoundException("Selection process not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Selection process with id = {id}"); | |||
| _mapper.Map(selectionProcessUpdateStatusDto, selectionProcess); | |||
| _logger.LogInformation($"Selection process with id = {id} mapped successfully"); | |||
| _context.Entry(selectionProcess).State = EntityState.Modified; | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Selection process saved to DB"); | |||
| await result; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,19 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class PatternApplicantViewDto | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public string Email { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,15 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class ScheduleInterviewDto | |||
| { | |||
| public List<string> Emails { get; set; } | |||
| public int PatternId { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class ScheduleInterviewResponseDto | |||
| { | |||
| public List<string> NotSentEmails { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,13 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class SelectionProcessUpdateStatusDto | |||
| { | |||
| public string Status { get; set; } | |||
| } | |||
| } | |||
| @@ -26,6 +26,11 @@ namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| public async Task<IActionResult> GetFilteredPatterns([FromQuery] FilterPatternDto request) => | |||
| Ok(await _patternService.GetFilteredPatternsAsync(request)); | |||
| [HttpGet("corresponding-pattern-applicants/{id}")] | |||
| public async Task<IActionResult> GetFilteredPatterns([FromRoute] int id) => | |||
| Ok(await _patternService.GetCorrespondingPatternApplicants(id)); | |||
| [HttpPost] | |||
| public async Task<IActionResult> Create([FromBody] PatternCreateDto request) | |||
| { | |||
| @@ -33,6 +38,14 @@ namespace Diligent.WebAPI.Host.Controllers.V1 | |||
| return StatusCode((int)HttpStatusCode.Created); | |||
| } | |||
| [HttpPost("schedule-interview")] | |||
| public async Task<IActionResult> ScheduleInterview([FromBody] ScheduleInterviewDto request) | |||
| { | |||
| var result = await _patternService.ScheduleIntrviewAsync(request); | |||
| return Ok(result); | |||
| } | |||
| [HttpPut("{id}")] | |||
| public async Task<IActionResult> Update([FromBody]PatternUpdateDto request, [FromRoute]int id) | |||
| { | |||