| @@ -1,58 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public static class AdExtensions | |||
| { | |||
| public static List<Ad> Filter(this List<Ad> query, AdFilterDto filters) => | |||
| query.FilterByExperience(filters.MinExperience, filters.MaxExperience).FilterByWorkType(filters.WorkHour).FilterByEmploymentType(filters.EmploymentType).ToList().FilterByTechnologies(filters.Technologies); | |||
| public static List<Ad> FilterByExperience(this List<Ad> query, int minExperience, int maxExperience) => | |||
| minExperience >= maxExperience ? query.Where(x => x.MinimumExperience >= minExperience && x.MinimumExperience <= maxExperience).ToList() | |||
| : query.Where(x => x.MinimumExperience >= minExperience && x.MinimumExperience <= maxExperience).ToList(); | |||
| public static List<Ad> FilterByWorkType(this List<Ad> query, string workHour) => | |||
| workHour.ToLower() == "parttime" ? query.Where(x => x.WorkHour == WorkHours.PartTime).ToList() : query.Where(x => x.WorkHour == WorkHours.FullTime).ToList(); | |||
| public static List<Ad> FilterByEmploymentType(this List<Ad> query, string employmentType) => | |||
| employmentType.ToLower() == "intership" ? query.Where(x => x.EmploymentType == EmploymentTypes.Intership).ToList() : query.Where(x => x.EmploymentType == EmploymentTypes.Work).ToList(); | |||
| public static List<Ad> FilterByTechnologies(this List<Ad> query, string[] technologies) | |||
| { | |||
| if (technologies == null || technologies.Length == 0) | |||
| { | |||
| return query; | |||
| } | |||
| List<Ad> filteredAds = new List<Ad>(); | |||
| for (int i = 0; i < query.Count(); i++) | |||
| { | |||
| for (int j = 0; j < query[i].Technologies.Count(); j++) | |||
| { | |||
| var s = 0; | |||
| for (int k = 0; k < technologies.Length; k++) | |||
| { | |||
| if (query[i].Technologies[j].Name.ToLower() == technologies[k].ToLower()) | |||
| { | |||
| s = 1; | |||
| } | |||
| } | |||
| if (s == 1) | |||
| { | |||
| filteredAds.Add(query[i]); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return filteredAds; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,88 +0,0 @@ | |||
| using System.Diagnostics.CodeAnalysis; | |||
| using static Diligent.WebAPI.Data.Entities.Applicant; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public static class ApplicantExtensions | |||
| { | |||
| public static List<Applicant> FilterApplicants(this List<Applicant> query,ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| return query.FilterByExperience(applicantFilterDto.MinExperience, applicantFilterDto.MaxExperience) | |||
| .FilterByEmploymentType(applicantFilterDto.EmploymentType) | |||
| .FilterByDateOfApplication(applicantFilterDto.MinDateOfApplication, applicantFilterDto.MaxDateOfApplication) | |||
| .FilterByTechnologies(applicantFilterDto.Technologies).ToList(); | |||
| } | |||
| public static List<Ad> FilterAdApplicants(this List<Ad> query, ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| List<Ad> filteredAds = new(); | |||
| List<List<Applicant>> applicants = new(); | |||
| for (int i = 0; i < query.Count; i++) | |||
| { | |||
| var app = query[i].Applicants.FilterApplicants(applicantFilterDto); | |||
| applicants.Add(app); | |||
| var k = query[i]; | |||
| k.Applicants = applicants[i]; | |||
| filteredAds.Add(k); | |||
| } | |||
| return filteredAds; | |||
| } | |||
| private static List<Applicant> FilterByExperience(this List<Applicant> query, int minExperience, int maxExperience) | |||
| { | |||
| if ((minExperience == 0 && maxExperience == 0) || minExperience > maxExperience) return query; | |||
| return query.Where(x => x.Experience >= minExperience && x.Experience <= maxExperience).ToList(); | |||
| } | |||
| private static List<Applicant> FilterByEmploymentType(this List<Applicant> query, string? employmentType) | |||
| { | |||
| if (employmentType == null) return query; | |||
| return query.Where(x => x.TypeOfEmployment == Enum.Parse<TypesOfEmployment>(employmentType)).ToList(); | |||
| } | |||
| private static List<Applicant> FilterByDateOfApplication(this List<Applicant> query, DateTime? minDateOfApplication, DateTime? maxDateOfApplication) | |||
| { | |||
| if (minDateOfApplication == null) return query; | |||
| if (minDateOfApplication > maxDateOfApplication) return query; | |||
| if (maxDateOfApplication == null) return query.Where(x => x.DateOfApplication >= minDateOfApplication && x.DateOfApplication <= DateTime.Now).ToList(); | |||
| return query.Where(x => x.DateOfApplication >= minDateOfApplication && x.DateOfApplication < maxDateOfApplication).ToList(); | |||
| } | |||
| private static List<Applicant> FilterByTechnologies(this List<Applicant> query, string[]? technologies) | |||
| { | |||
| if (technologies is null) | |||
| { | |||
| return query; | |||
| } | |||
| List<Applicant> filteredApplicants = new(); | |||
| for (int i = 0; i < query.Count; i++) | |||
| { | |||
| for (int j = 0; j < query[i].TechnologyApplicants.Count; j++) | |||
| { | |||
| bool s = false; | |||
| for (int n = 0; n < technologies.Length; n++) | |||
| { | |||
| if (query[i].TechnologyApplicants[j].Technology.Name.ToLower() == technologies[n].ToLower()) | |||
| { | |||
| s = true; | |||
| break; | |||
| } | |||
| } | |||
| if (s) | |||
| { | |||
| filteredApplicants.Add(query[i]); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return filteredApplicants; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,52 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Pattern; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public static class PatternExtension | |||
| { | |||
| public static List<Pattern> FilterApplicants(this List<Pattern> query, FilterPatternDto filterPatternDto) | |||
| { | |||
| return query.FilterByDate(filterPatternDto.FromDate, filterPatternDto.ToDate) | |||
| .FilterBySelectionLevels(filterPatternDto.SelectionLevels) | |||
| .ToList(); | |||
| } | |||
| private static List<Pattern> FilterByDate(this List<Pattern> query, DateTime? fromDate, DateTime? toDate) | |||
| { | |||
| if(fromDate == null && toDate == null) return query; | |||
| if(fromDate == null && toDate != null) return query.Where(x => x.CreatedAt <= toDate).ToList(); | |||
| if ((fromDate != null && toDate == null) || (fromDate > toDate)) return query.Where(x => x.CreatedAt >= fromDate).ToList(); | |||
| return query.Where(x => x.CreatedAt >= fromDate && x.CreatedAt < toDate).ToList(); | |||
| } | |||
| private static List<Pattern> FilterBySelectionLevels(this List<Pattern> query, int[]? selectionLevels) | |||
| { | |||
| if (selectionLevels is null) | |||
| { | |||
| return query; | |||
| } | |||
| List<Pattern> filteredPatterns = new(); | |||
| for (int i = 0; i < query.Count; i++) | |||
| { | |||
| for(int j = 0; j < selectionLevels.Length; j++) | |||
| { | |||
| if (query[i].SelectionLevelId == selectionLevels[j]) | |||
| { | |||
| filteredPatterns.Add(query[i]); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return filteredPatterns; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,38 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Extensions | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public static class SelectionProcessExtensions | |||
| { | |||
| public static List<SelectionLevel> FilterLevels(this List<SelectionLevel> query, SelectionProcessFilterDto filter) | |||
| { | |||
| var filteredLevels = new List<SelectionLevel>(); | |||
| // If filters are empty | |||
| if ((filter == null) || (!filter.DateStart.HasValue && !filter.DateEnd.HasValue && filter.Statuses != null && filter.Statuses.Length == 0)) | |||
| return query; | |||
| foreach (var level in query) | |||
| { | |||
| List<SelectionProcess> selectionProcesses = level.SelectionProcesses; | |||
| if (filter.DateStart.HasValue) | |||
| { | |||
| selectionProcesses = level.SelectionProcesses.Where(sp => sp.Date >= filter.DateStart.Value).ToList(); | |||
| } | |||
| if (filter.DateEnd.HasValue) | |||
| { | |||
| selectionProcesses = selectionProcesses.Where(sp => sp.Date <= filter.DateEnd.Value).ToList(); | |||
| } | |||
| var filteredLevel = new SelectionLevel { Id = level.Id, Name = level.Name, SelectionProcesses = level.SelectionProcesses}; | |||
| if(filter.Statuses != null && filter.Statuses.Length > 0) { | |||
| filteredLevel.SelectionProcesses = selectionProcesses.Where(f => filter.Statuses.Contains(f.Status)).ToList(); | |||
| } | |||
| filteredLevels.Add(filteredLevel); | |||
| } | |||
| return filteredLevels; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,25 +0,0 @@ | |||
| | |||
| using System.Diagnostics.CodeAnalysis; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class AdMappingProfile : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public AdMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<AdCreateDto, Ad>(); | |||
| CreateMap<AdUpdateDto, Ad>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<Ad, AdResponseDto>(); | |||
| CreateMap<Ad, AdDetailsResponseDto>(); | |||
| CreateMap<Ad, AdApplicantsViewDto>(); | |||
| CreateMap<Ad, AdResponseWithCountDto>() | |||
| .ForMember(dest => dest.Count, opt => opt.MapFrom(x => x.Applicants.Count)); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class ApplicantMappingProfile:Profile | |||
| { | |||
| public ApplicantMappingProfile() | |||
| { | |||
| #region Models to DTOs | |||
| CreateMap<Applicant, ApplicantViewDto>(); | |||
| CreateMap<Applicant, AdApplicantViewDto>(); | |||
| CreateMap<Applicant, ApplicantScheduleViewDto>(); | |||
| CreateMap<Applicant, PatternApplicantViewDto>(); | |||
| CreateMap<Applicant, ApplicantOptionsDTO>(); | |||
| #endregion | |||
| #region DTOs to Models | |||
| CreateMap<ApplicantImportDto, Applicant>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Comment; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class CommentMappingProfile:Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public CommentMappingProfile() | |||
| { | |||
| #region Models to DTO | |||
| CreateMap<Comment, CommentViewDto>(); | |||
| #endregion | |||
| #region DTO to Model | |||
| CreateMap<CommentCreateDto, Comment>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,20 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class CompanyMappingProfile : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public CompanyMappingProfile() | |||
| { | |||
| #region Models to DTOs | |||
| CreateMap<InsuranceCompany, InsuranceCompanyViewDto>(); | |||
| #endregion | |||
| #region DTOs to Models | |||
| CreateMap<InsuranceCompanyCreateDto, InsuranceCompany>(); | |||
| CreateMap<InsuranceCompanyUpdateDto, InsuranceCompany>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class InsurerMappingProfile : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public InsurerMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<InsurerCreateDto, Insurer>(); | |||
| CreateMap<InsurerUpdateDto, Insurer>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<Insurer, InsurerViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,25 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Pattern; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class PatternMappingProfile : Profile | |||
| { | |||
| public PatternMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<PatternCreateDto, Pattern>(); | |||
| CreateMap<PatternUpdateDto, Pattern>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<Pattern, PatternResponseDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class PolicyMappingProfiles : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public PolicyMappingProfiles() | |||
| { | |||
| CreateMap<InsurancePolicy, InsurancePolicyViewDto>(); | |||
| CreateMap<InsurancePolicyCreateDto, InsurancePolicy>(); | |||
| CreateMap<InsurancePolicyUpdateDto, InsurancePolicy>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class SelectionLevelMappingProfile : Profile | |||
| { | |||
| public SelectionLevelMappingProfile() | |||
| { | |||
| #region Model to DTO | |||
| CreateMap<SelectionLevel, SelectionLevelResposneDto>(); | |||
| CreateMap<SelectionLevel, SelectionLevelResponseWithDataDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,23 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Schedule; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class SelectionProcessMappingProfile : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public SelectionProcessMappingProfile() | |||
| { | |||
| #region DTO to Model | |||
| CreateMap<SelectionProcessCreateDto, SelectionProcess>(); | |||
| CreateMap<SelectionProcessUpdateStatusDto, SelectionProcess>(); | |||
| #endregion | |||
| #region Model to DTO | |||
| CreateMap<SelectionProcess, SelectionProcessResposneDto>(); | |||
| CreateMap<SelectionProcess, SelectionProcessResposneWithoutApplicantDto>(); | |||
| CreateMap<SelectionProcess, ScheduleViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,16 +0,0 @@ | |||
| | |||
| namespace Diligent.WebAPI.Business.MappingProfiles | |||
| { | |||
| public class TechnologyMappingProfile : Profile | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public TechnologyMappingProfile() | |||
| { | |||
| #region Model to DTO | |||
| CreateMap<Technology, TechnologyResponseDto>(); | |||
| //CreateMap<TechnologyApplicant, TechnologyResponseDto>(); -- ermin | |||
| CreateMap<TechnologyApplicant, TechnologyViewDto>(); | |||
| #endregion | |||
| } | |||
| } | |||
| } | |||
| @@ -1,215 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class AdService : IAdService | |||
| { | |||
| private readonly ILogger<AdService> _logger; | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ITechnologyService _technologyService; | |||
| public AdService(DatabaseContext context, IMapper mapper, ITechnologyService technologyService, ILogger<AdService> logger) | |||
| { | |||
| _logger = logger; | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _technologyService = technologyService; | |||
| } | |||
| public async Task<List<AdResponseDto>> GetAllAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all Ads"); | |||
| var today = DateTime.Now; | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var fromDb = await _context.Ads.Include(x => x.Technologies).Where(x => x.ExpiredAt > today).ToListAsync(); | |||
| _logger.LogInformation($"Received {fromDb.Count} ads from db."); | |||
| _logger.LogInformation($"Mapping received ads to AdResponseDto"); | |||
| var result = _mapper.Map<List<AdResponseDto>>(fromDb); | |||
| _logger.LogInformation($"Ads has been mapped and received to client: {result.Count} mapped ads"); | |||
| return result; | |||
| } | |||
| public async Task<List<AdResponseWithCountDto>> GetAllWithCountAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all Ads with applicants count"); | |||
| var today = DateTime.Now; | |||
| _logger.LogInformation("Getting data from database"); | |||
| var res = _mapper.Map<List<AdResponseWithCountDto>>(await _context.Ads.Include(x => x.Applicants).Where(x => x.ExpiredAt > today).ToListAsync()); | |||
| _logger.LogInformation($"Received {res.Count} ads with their counts"); | |||
| return res; | |||
| } | |||
| public async Task<AdResponseDto> GetByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Ad with id = {id}"); | |||
| AdResponseDto result = _mapper.Map<AdResponseDto>(ad); | |||
| _logger.LogInformation($"Ad with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<AdDetailsResponseDto> GetAdDetailsByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start finding Ad with id = {id} with applicants"); | |||
| var ad = await _context.Ads.Include(x => x.Applicants).Where(x => x.Id == id).FirstOrDefaultAsync(); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Ad with id = {id}"); | |||
| AdDetailsResponseDto result = _mapper.Map<AdDetailsResponseDto>(ad); | |||
| _logger.LogInformation($"Ad with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<List<AdResponseDto>> GetArchiveAds() | |||
| { | |||
| _logger.LogInformation("Start getting all Archived Ads"); | |||
| var today = DateTime.Now; | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var archiveAds = await _context.Ads.Where(x => x.ExpiredAt < today).ToListAsync(); | |||
| _logger.LogInformation($"Received {archiveAds.Count} ads from db."); | |||
| _logger.LogInformation($"Mapping received ads to AdResponseDto"); | |||
| List<AdResponseDto> result = _mapper.Map<List<AdResponseDto>>(archiveAds); | |||
| _logger.LogInformation($"Ads has been mapped and received to client: {result.Count} mapped ads"); | |||
| return result; | |||
| } | |||
| public async Task<List<AdResponseDto>> GetFilteredAdsAsync(AdFilterDto filters) | |||
| { | |||
| _logger.LogInformation($"Start getting all filtered Ads"); | |||
| var today = DateTime.Now; | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var filteredAds = await _context.Ads.Include(x => x.Technologies).Where(x => x.ExpiredAt > today).ToListAsync(); | |||
| _logger.LogInformation($"Received {filteredAds.Count} ads from db."); | |||
| _logger.LogInformation($"Mapping received ads to AdResponseDto"); | |||
| List<AdResponseDto> result = _mapper.Map<List<AdResponseDto>>(filteredAds.Filter(filters)); | |||
| _logger.LogInformation($"Ads has been mapped and received to client: {result.Count} mapped ads"); | |||
| return result; | |||
| } | |||
| public async Task CreateAsync(AdCreateDto adCreateDto) | |||
| { | |||
| _logger.LogInformation($"Start creating Ad"); | |||
| var ad = _mapper.Map<Ad>(adCreateDto); | |||
| _logger.LogInformation($"Ad created successfully"); | |||
| _logger.LogInformation($"Start adding technologies to Ad"); | |||
| for (int i = 0; i < adCreateDto.TechnologiesIds.Count; i++) | |||
| { | |||
| var technology = await _technologyService.GetEntityByIdAsync(adCreateDto.TechnologiesIds[i]); | |||
| ad.Technologies.Add(technology); | |||
| _logger.LogInformation($"Technology with id {technology.TechnologyId} added to Ad"); | |||
| } | |||
| _logger.LogInformation($"Finished adding techonologies"); | |||
| await _context.Ads.AddAsync(ad); | |||
| _logger.LogInformation($"Saving Ad to db..."); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| await result; | |||
| } | |||
| public async Task UpdateAsync(int id, AdUpdateDto adUpdateDto) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Ad with id = {id}"); | |||
| _mapper.Map(adUpdateDto, ad); | |||
| _logger.LogInformation($"Ad with id = {id} mapped successfully"); | |||
| _context.Entry(ad).State = EntityState.Modified; | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| await result; | |||
| } | |||
| public async Task ArchiveAdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| _logger.LogInformation($"Change ad expired time"); | |||
| ad.ExpiredAt = DateTime.Now; | |||
| _logger.LogInformation($"Ad expired time changed successfully"); | |||
| _context.Entry(ad).State = EntityState.Modified; | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| await result; | |||
| } | |||
| public async Task DeleteAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| _context.Ads.Remove(ad); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| await result; | |||
| } | |||
| public async Task<Ad> ImportAsync(AdCreateDto adCreateDto) | |||
| { | |||
| _logger.LogInformation($"Start importing Ad"); | |||
| var ad = _mapper.Map<Ad>(adCreateDto); | |||
| _logger.LogInformation($"Ad imported successfully"); | |||
| await _context.Ads.AddAsync(ad); | |||
| _logger.LogInformation($"Saving Ad to db..."); | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| return ad; | |||
| } | |||
| public async Task<Ad> GetByIdEntityAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var ad = await _context.Ads.FindAsync(id); | |||
| if (ad is null) | |||
| { | |||
| _logger.LogError($"Ad with id = {id} not found"); | |||
| throw new EntityNotFoundException("Ad not found"); | |||
| } | |||
| return ad; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,287 +0,0 @@ | |||
| using static Diligent.WebAPI.Data.Entities.Applicant; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class ApplicantService : IApplicantService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ILogger<ApplicantService> _logger; | |||
| private readonly IUserService _userService; | |||
| private readonly IFileService _fileService; | |||
| private readonly IAdService _adService; | |||
| private readonly ITechnologyService _technologyService; | |||
| public ApplicantService(DatabaseContext context, IMapper mapper, ILogger<ApplicantService> logger, | |||
| IUserService userService,IFileService fileService,IAdService adService,ITechnologyService technologyService) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| _userService = userService; | |||
| _fileService = fileService; | |||
| _adService = adService; | |||
| _technologyService = technologyService; | |||
| } | |||
| public async Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| _logger.LogInformation("Start getting filtered applicants"); | |||
| _logger.LogInformation("Getting data from DB and filter"); | |||
| var filteredApplicants = (await _context.Applicants | |||
| .Include(c => c.Ads) | |||
| .Include(x => x.TechnologyApplicants) | |||
| .ThenInclude(x => x.Technology).ToListAsync()) | |||
| .FilterApplicants(applicantFilterDto); | |||
| int totalNumberOfItems = filteredApplicants.Count; | |||
| _logger.LogInformation($"Got {totalNumberOfItems} applicants"); | |||
| filteredApplicants = PaginationExtension.ApplyPagging(filteredApplicants, new Pagination | |||
| { | |||
| CurrentPage = applicantFilterDto.CurrentPage, | |||
| PageSize = applicantFilterDto.PageSize | |||
| }); | |||
| _logger.LogInformation($"Return list of applicants"); | |||
| return new QueryResultDto<ApplicantViewDto> | |||
| { | |||
| Items = _mapper.Map<List<ApplicantViewDto>>(filteredApplicants), | |||
| Total = totalNumberOfItems | |||
| }; | |||
| } | |||
| public async Task<ApplicantViewDto> GetById(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {id}"); | |||
| var applicant = await _context.Applicants | |||
| .Include(x => x.Ads) | |||
| .ThenInclude(x => x.Technologies) | |||
| .Include(x => x.TechnologyApplicants) | |||
| .ThenInclude(x => x.Technology) | |||
| .Include(x => x.Comments) | |||
| .ThenInclude(t => t.User) | |||
| .FirstOrDefaultAsync(x => x.ApplicantId == id); | |||
| if (applicant is null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {id} not found"); | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Applicant with id = {id}"); | |||
| var result = _mapper.Map<ApplicantViewDto>(applicant); | |||
| result.CV = await _fileService.GetCV("638077305621281656.pdf"); | |||
| _logger.LogInformation($"Applicant with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {id}"); | |||
| var applicant = await _context.Applicants | |||
| .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.SelectionLevel) | |||
| .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.Scheduler) | |||
| .FirstOrDefaultAsync(a => a.ApplicantId == id); | |||
| if (applicant is null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {id} not found"); | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| } | |||
| _logger.LogInformation($"Applicant with id = {id} mapped successfully"); | |||
| return _mapper.Map<ApplicantViewDto>(applicant); | |||
| } | |||
| public async Task DeleteApplicant(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {id}"); | |||
| var applicant = await _context.Applicants.FindAsync(id); | |||
| if (applicant is null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {id} not found"); | |||
| throw new EntityNotFoundException("Applicant not found"); | |||
| } | |||
| _logger.LogInformation($"Removing Applicant with id = {id}"); | |||
| _context.Applicants.Remove(applicant); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Applicant with id = {id} is removed successfully"); | |||
| await result; | |||
| } | |||
| public async Task<List<AdApplicantsViewDto>> GetAllAdsApplicants(ApplicantFilterDto applicantFilterDto) | |||
| { | |||
| _logger.LogInformation("Start getting filtered applicants"); | |||
| _logger.LogInformation("Getting data from DB and filter"); | |||
| var adsApplicants = (await _context.Ads | |||
| .Include(a => a.Applicants) | |||
| .ThenInclude(a => a.TechnologyApplicants) | |||
| .ThenInclude(a => a.Technology) | |||
| .ToListAsync()) | |||
| .FilterAdApplicants(applicantFilterDto); | |||
| _logger.LogInformation($"Got {adsApplicants.Count} ads"); | |||
| _logger.LogInformation("Mapping received Ads to AdApplicantsViewDto"); | |||
| var result = _mapper.Map<List<AdApplicantsViewDto>>(adsApplicants); | |||
| _logger.LogInformation($"Ads mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task ApplyForAd(ApplyForAdRequestDto request) | |||
| { | |||
| string fileName = string.Format(@"{0}.pdf", DateTime.Now.Ticks); | |||
| _logger.LogInformation($"Start uploading CV of applicant on Azure Blob storage"); | |||
| await _fileService.UploadCV(fileName, request.PdfFile); | |||
| _logger.LogInformation($"CV uploaded on Azure Blob storage"); | |||
| _logger.LogInformation("Start applying for ad"); | |||
| _logger.LogInformation("Find ad by id"); | |||
| var ad = await _adService.GetByIdEntityAsync(request.AdId); | |||
| if (ad == null) | |||
| { | |||
| _logger.LogError($"Ad with {request.AdId} not found"); | |||
| throw new EntityNotFoundException("Ad not found in database"); | |||
| } | |||
| _logger.LogInformation($"Find sent technologies from FE in database"); | |||
| //var technologies = await _context.Technologies.Where(x => request.TechnologiesIds.Contains(x.TechnologyId)).ToListAsync(); | |||
| var technologies = await _technologyService.GetEntitiesAsync(request.TechnologiesIds); | |||
| _logger.LogInformation($"Create applicant instance with sent data"); | |||
| Applicant applicant = new() | |||
| { | |||
| FirstName = request.FirstName, | |||
| LastName = request.LastName, | |||
| Position = ad.Title, | |||
| DateOfApplication = DateTime.Now, | |||
| CV = fileName, | |||
| Email = request.Email, | |||
| PhoneNumber = request.PhoneNumber, | |||
| GithubLink = request.GithubLink, | |||
| LinkedlnLink = request.LinkedinLink, | |||
| BitBucketLink = request.BitBucketLink, | |||
| Experience = request.Experience, | |||
| //TypeOfEmployment = (EmploymentTypes)Enum.Parse(typeof(EmploymentTypes), ad.EmploymentType, true), | |||
| TypeOfEmployment = ad.EmploymentType == EmploymentTypes.Intership ? TypesOfEmployment.Intership : TypesOfEmployment.Posao, | |||
| Comments = new(), | |||
| Ads = new List<Ad> { ad }, | |||
| SelectionProcesses = new(), | |||
| TechnologyApplicants = new(), | |||
| ApplicationChannel = "Putem sajta", | |||
| Gender = request.Gender == "Muski" ? Genders.M : Genders.Z, | |||
| ProfessionalQualification = request.ProfessionalQualification | |||
| }; | |||
| _logger.LogInformation($"Saving applicant in database"); | |||
| await _context.Applicants.AddAsync(applicant); | |||
| var res = await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Applicant saved in database"); | |||
| _logger.LogInformation($"Saving TechnologyApplicants in database"); | |||
| for (int i = 0; i < technologies.Count; i++) | |||
| { | |||
| await _context.ApplicantTechnologies.AddAsync(new TechnologyApplicant { Applicant = applicant, ApplicantId = applicant.ApplicantId, Technology = technologies[i], TechnologyId = technologies[i].TechnologyId }); | |||
| } | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"TechnologyApplicants saved in database"); | |||
| } | |||
| public async Task ImportApplicant(List<ApplicantImportDto> requests) | |||
| { | |||
| _logger.LogInformation($"Create applicant instance with sent data"); | |||
| var res = new List<Applicant>(); | |||
| _logger.LogInformation($"Get first user from database"); | |||
| var user = await _userService.GetFirst(); | |||
| _logger.LogInformation($"User succesufully fetched from database"); | |||
| foreach (var request in requests) { | |||
| Applicant applicant = new Applicant | |||
| { | |||
| FirstName = request.FirstName ?? "", | |||
| LastName = request.LastName ?? "", | |||
| CV = request.CV ?? "", | |||
| Email = request.Email ?? "", | |||
| PhoneNumber = request.PhoneNumber ?? "", | |||
| GithubLink = request.GithubLink ?? "", | |||
| LinkedlnLink = request.LinkedlnLink ?? "", | |||
| BitBucketLink = request.BitBucketLink ?? "", | |||
| Position = "", | |||
| DateOfApplication = request.DateOfApplication, | |||
| TypeOfEmployment = request.TypeOfEmployment == "Praksa" ? TypesOfEmployment.Intership : TypesOfEmployment.Posao, | |||
| Experience = request.Experience, | |||
| ApplicationChannel = request.ApplicationChannel ?? "Putem sajta", | |||
| // MORA DA SE UVEDE KO JE DAO KOMENTAR DA LI DA STAVIMO DA JE DANIJELA SVIMA STAVILA KOMENTARE ILI ?? | |||
| Comments = new List<Comment> | |||
| { | |||
| new Comment | |||
| { | |||
| User = user, | |||
| Content = request.Comment | |||
| } | |||
| }, | |||
| Ads = new List<Ad> { request.Ad }, | |||
| SelectionProcesses = new(), | |||
| TechnologyApplicants = new(), | |||
| Gender = Genders.M, | |||
| ProfessionalQualification = "Elektrotehnicki fakultet", | |||
| }; | |||
| res.Add(applicant); | |||
| } | |||
| _logger.LogInformation($"Saving applicants in database"); | |||
| await _context.AddRangeAsync(res); | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Applicants saved in database"); | |||
| } | |||
| public async Task<List<ApplicantOptionsDTO>> GetOptions() | |||
| { | |||
| _logger.LogInformation($"Start getting all applicants from database"); | |||
| var res = await _context.Applicants.ToListAsync(); | |||
| _logger.LogInformation($"Got {res.Count} applicants"); | |||
| return _mapper.Map<List<ApplicantOptionsDTO>>(res); | |||
| } | |||
| public async Task<ServiceResponseDTO<object>> InitializeProcess(ApplicantProcessRequestDTO model) | |||
| { | |||
| _logger.LogInformation($"Start searching Applicant with id = {model.ApplicantId}"); | |||
| var applicant = await _context.Applicants.Include(n => n.SelectionProcesses).Where(n=> n.ApplicantId ==model.ApplicantId).FirstOrDefaultAsync(); | |||
| if (applicant == null) | |||
| { | |||
| _logger.LogError($"Applicant with id = {model.ApplicantId} not found"); | |||
| return new ServiceResponseDTO<object> | |||
| { | |||
| IsError = true, | |||
| ErrorMessage = "Applicant does not exist." | |||
| }; | |||
| } | |||
| applicant.SelectionProcesses.Add(new SelectionProcess | |||
| { | |||
| Name = StringGenerator.GenerateRandomPassword(), | |||
| SchedulerId = model.SchedulerId, | |||
| SelectionLevelId = 1, | |||
| Status = model.Appointment != null ? "Zakazan" : "Čeka na zakazivanje", | |||
| Date = model.Appointment | |||
| }); | |||
| _logger.LogInformation($"Saving selection processes in database"); | |||
| await _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Selecetion processes saved in database"); | |||
| return new ServiceResponseDTO<object> | |||
| { | |||
| Data = true | |||
| }; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,14 +1,4 @@ | |||
| using Dapper; | |||
| using Diligent.WebAPI.Business.Services.Interfaces; | |||
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||
| using Microsoft.Extensions.Configuration; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Data.SqlClient; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| using Diligent.WebAPI.Contracts.DTOs.Categories; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class CategoryService : ICategoryService | |||
| @@ -198,7 +188,7 @@ namespace Diligent.WebAPI.Business.Services | |||
| bool s = false; | |||
| for (int i = 0; i < k.Count; i++) | |||
| { | |||
| if(category.Id == k[i].CategoryId) | |||
| if (category.Id == k[i].CategoryId) | |||
| { | |||
| s = true; | |||
| break; | |||
| @@ -209,11 +199,11 @@ namespace Diligent.WebAPI.Business.Services | |||
| t.Add(m.Category); | |||
| break; | |||
| } | |||
| else if(!s && category.ParentCategory is null) | |||
| else if (!s && category.ParentCategory is null) | |||
| { | |||
| break; | |||
| } | |||
| else if(s == true) | |||
| else if (s == true) | |||
| { | |||
| category = category.ParentCategory; | |||
| continue; | |||
| @@ -223,9 +213,9 @@ namespace Diligent.WebAPI.Business.Services | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| return t; | |||
| } | |||
| private List<TreeViewCategoryResponse> GetTreeCategoryItem(List<Category> items, int id) | |||
| @@ -254,14 +244,17 @@ namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| category = await _context.Categories.Where(x => x.Id == createCategoryDto.ParentId).FirstOrDefaultAsync(); | |||
| } | |||
| var newCategory = new Category { Name = createCategoryDto.Name, ParentCategory = category }; | |||
| await _context.Categories.AddAsync(newCategory); | |||
| await _context.SaveChangesAsync(); | |||
| await _userService.GrantCategoryToUserAsync(new GrantUserCategoryRequestDto { UserId = userId, Categories = new List<GrantCategoryToUserRequestDto> { new GrantCategoryToUserRequestDto { Id = newCategory.Id, IsChecked = true } } }); | |||
| await _userService.GrantCategoryToUserAsync(new GrantUserCategoryRequestDto { | |||
| UserId = userId, Categories = new List<GrantCategoryToUserRequestDto> { | |||
| new GrantCategoryToUserRequestDto { Id = newCategory.Id, IsChecked = true } | |||
| } | |||
| }); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,42 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class CommentService : ICommentService | |||
| { | |||
| private readonly FrontEndSettings _frontEndSettings; | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ILogger<CommentService> _logger; | |||
| private readonly IEmailer _emailer; | |||
| public CommentService(IOptions<FrontEndSettings> frontEndSettings,DatabaseContext context, IMapper mapper, ILogger<CommentService> logger,IEmailer emailer) | |||
| { | |||
| _frontEndSettings = frontEndSettings.Value; | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| _emailer = emailer; | |||
| } | |||
| public async Task CreateComment(CommentCreateDto commentCreateDto) | |||
| { | |||
| _logger.LogInformation("Start creating comment"); | |||
| var comment = _mapper.Map<Comment>(commentCreateDto); | |||
| if(commentCreateDto.UsersToNotify.Count > 0) | |||
| { | |||
| _logger.LogInformation("Start sending emails"); | |||
| await _emailer.SendEmailAsync(commentCreateDto.UsersToNotify, "You're tagged in comment by another user", | |||
| HTMLHelper.RenderTagPage($"{_frontEndSettings.BaseUrl}/candidates/{commentCreateDto.ApplicantId}"), isHtml: true); | |||
| _logger.LogInformation("Emails send successfully"); | |||
| } | |||
| comment.DateOfSending = DateTime.Now; | |||
| _logger.LogInformation($"Comment created successfully in {comment.DateOfSending}"); | |||
| _logger.LogInformation($"Saving comment in Db"); | |||
| await _context.Comments.AddAsync(comment); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Comment saved in Db"); | |||
| await result; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,55 +0,0 @@ | |||
| using Microsoft.AspNetCore.Http; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class ImportService : IImportService | |||
| { | |||
| private readonly ILogger<ImportService> _logger; | |||
| private readonly ISaveImportedDataService _service; | |||
| public ImportService(ILogger<ImportService> logger, ISaveImportedDataService service) | |||
| { | |||
| _logger = logger; | |||
| _service = service; | |||
| } | |||
| public async Task<List<ApplicantImportDto>> Import(IFormFile fileData) | |||
| { | |||
| try | |||
| { | |||
| using (var stream = new MemoryStream()) | |||
| { | |||
| fileData.CopyTo(stream); | |||
| var FileData = stream.ToArray(); | |||
| CopyFileToDirectory(FileData); | |||
| } | |||
| return await _service.Save(); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| throw new Exception(ex.Message); | |||
| } | |||
| return new List<ApplicantImportDto>(); | |||
| } | |||
| private async Task CopyFileToDirectory(byte[] FileData) | |||
| { | |||
| try | |||
| { | |||
| var content = new System.IO.MemoryStream(FileData); | |||
| var path = Path.Combine(Directory.GetCurrentDirectory(), "Files", "s.xlsx"); | |||
| await CopyStream(content, path); | |||
| } | |||
| catch (Exception) | |||
| { | |||
| throw; | |||
| } | |||
| } | |||
| private async Task CopyStream(Stream stream, string downloadPath) | |||
| { | |||
| using (var fileStream = new FileStream(downloadPath, FileMode.Create, FileAccess.Write)) | |||
| { | |||
| await stream.CopyToAsync(fileStream); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,64 +0,0 @@ | |||
| using System.Diagnostics.CodeAnalysis; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class InsuranceCompaniesService : IInsuranceCompaniesService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public InsuranceCompaniesService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsuranceCompanyViewDto>> GetInsuranceCompanies() | |||
| { | |||
| var insuranceCompanies = await _context.InsuranceCompanies.ToListAsync(); | |||
| var insuranceCompaniesDto = _mapper.Map<List<InsuranceCompanyViewDto>>(insuranceCompanies); | |||
| return insuranceCompaniesDto; | |||
| } | |||
| public async Task<InsuranceCompanyViewDto?> GetInsuranceCompany(long id) | |||
| { | |||
| var insuranceCompany = await _context.InsuranceCompanies.FindAsync(id); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException("Insurance company not found"); | |||
| var insuranceCompanyDto = _mapper.Map<InsuranceCompanyViewDto?>(insuranceCompany); | |||
| return insuranceCompanyDto; | |||
| } | |||
| public async Task CreateInsuranceCompany(InsuranceCompanyCreateDto insuranceCompanyCreateDto) | |||
| { | |||
| var insuranceCompany = _mapper.Map<InsuranceCompany>(insuranceCompanyCreateDto); | |||
| insuranceCompany.CreatedAtUtc = DateTime.Now; | |||
| await _context.InsuranceCompanies.AddAsync(insuranceCompany); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsuranceCompany(long insuranceCompanyId, InsuranceCompanyUpdateDto insuranceCompanyUpdateDto) | |||
| { | |||
| var insuranceCompany = _context.InsuranceCompanies.Find(insuranceCompanyId); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException($"Insurance company not found"); | |||
| _mapper.Map(insuranceCompanyUpdateDto, insuranceCompany); | |||
| insuranceCompany.UpdatedAtUtc = DateTime.Now; | |||
| _context.Entry(insuranceCompany).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsuranceCompany(long insuranceCompanyId) | |||
| { | |||
| var insuranceCompany = _context.InsuranceCompanies.Find(insuranceCompanyId); | |||
| if (insuranceCompany == null) | |||
| throw new EntityNotFoundException("Insurance company not found"); | |||
| _context.Remove(insuranceCompany); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,76 +0,0 @@ | |||
| using System.Diagnostics.CodeAnalysis; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class InsurancePoliciesService : IInsurancePoliciesService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IWebhookPublisherService _webhookPublisher; | |||
| private readonly IMapper _mapper; | |||
| public InsurancePoliciesService(DatabaseContext context, IWebhookPublisherService webhookPublisher, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _webhookPublisher = webhookPublisher; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsurancePolicyViewDto>> GetInsurancePolicies() | |||
| { | |||
| var insurancePolicies = await _context.InsurancePolicies | |||
| .Include(i => i.Insurer) | |||
| .ThenInclude(k => k.InsuranceCompany) | |||
| .ToListAsync(); | |||
| var insurancePoliciesDto = _mapper.Map<List<InsurancePolicyViewDto>>(insurancePolicies); | |||
| return insurancePoliciesDto; | |||
| } | |||
| public async Task<InsurancePolicyViewDto?> GetInsurancePolicy(long id) | |||
| { | |||
| var insurancePolicy = await _context.InsurancePolicies | |||
| .Include(i => i.Insurer) | |||
| .ThenInclude(k => k.InsuranceCompany) | |||
| .FirstOrDefaultAsync(i => i.Id == id); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| var insurancePolicyDto = _mapper.Map<InsurancePolicyViewDto>(insurancePolicy); | |||
| return insurancePolicyDto; | |||
| } | |||
| public async Task CreateInsurancePolicy(InsurancePolicyCreateDto insurancePolicyCreateDto) | |||
| { | |||
| var insurancePolicy = _mapper.Map<InsurancePolicy>(insurancePolicyCreateDto); | |||
| var result = await _context.InsurancePolicies.AddAsync(insurancePolicy); | |||
| await _webhookPublisher.PublishAsync("insurancePolicy.created", result); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsurancePolicy(long insurancePolicyId, InsurancePolicyUpdateDto insurancePolicyUpdateDto) | |||
| { | |||
| var insurancePolicy = _context.InsurancePolicies.Find(insurancePolicyId); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| _mapper.Map(insurancePolicyUpdateDto, insurancePolicy); | |||
| insurancePolicy.UpdatedAtUtc = DateTime.Now; | |||
| _context.Entry(insurancePolicy).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsurancePolicy(long insurancePolicyId) | |||
| { | |||
| var insurancePolicy = _context.InsurancePolicies.Find(insurancePolicyId); | |||
| if (insurancePolicy == null) | |||
| throw new EntityNotFoundException("Insurance policy not found"); | |||
| _context.Remove(insurancePolicy); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,66 +0,0 @@ | |||
| using System.Diagnostics.CodeAnalysis; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| [ExcludeFromCodeCoverage] | |||
| public class InsurersService : IInsurersService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| public InsurersService(DatabaseContext context, IMapper mapper) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| } | |||
| public async Task<List<InsurerViewDto>> GetInsurers() | |||
| { | |||
| var insurers = await _context.Insurers.Include(x => x.InsuranceCompany).ToListAsync(); | |||
| return _mapper.Map<List<InsurerViewDto>>(insurers); | |||
| } | |||
| public async Task<InsurerViewDto?> GetInsurer(long id) | |||
| { | |||
| var insurer = await _context.Insurers | |||
| .Include(x => x.InsuranceCompany) | |||
| .FirstOrDefaultAsync(x => x.Id == id); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| return _mapper.Map<InsurerViewDto>(insurer); | |||
| } | |||
| public async Task CreateInsurer(InsurerCreateDto insurerCreateDto) | |||
| { | |||
| var insurer = _mapper.Map<Insurer>(insurerCreateDto); | |||
| await _context.Insurers.AddAsync(insurer); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task UpdateInsurer(long insurerId, InsurerUpdateDto insurerUpdateDto) | |||
| { | |||
| var insurer = _context.InsurancePolicies.Find(insurerId); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| _mapper.Map(insurerUpdateDto, insurer); | |||
| insurer.UpdatedAtUtc = DateTime.Now; | |||
| _context.Entry(insurer).State = EntityState.Modified; | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task DeleteInsurerAsync(long insurerId) | |||
| { | |||
| var insurer = _context.InsurancePolicies.Find(insurerId); | |||
| if (insurer == null) | |||
| throw new EntityNotFoundException("Insurer not found"); | |||
| _context.Remove(insurer); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,27 +0,0 @@ | |||
| | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IAdService | |||
| { | |||
| Task<List<AdResponseDto>> GetAllAsync(); | |||
| Task<List<AdResponseWithCountDto>> GetAllWithCountAsync(); | |||
| Task<AdResponseDto> GetByIdAsync(int id); | |||
| Task<AdDetailsResponseDto> GetAdDetailsByIdAsync(int id); | |||
| Task<List<AdResponseDto>> GetArchiveAds(); | |||
| Task<List<AdResponseDto>> GetFilteredAdsAsync(AdFilterDto filters); | |||
| Task CreateAsync(AdCreateDto adCreateDto); | |||
| Task<Ad> ImportAsync(AdCreateDto adCreateDto); | |||
| Task UpdateAsync(int id, AdUpdateDto adUpdateDto); | |||
| Task ArchiveAdAsync(int id); | |||
| Task DeleteAsync(int id); | |||
| Task<Ad> GetByIdEntityAsync(int id); | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IApplicantService | |||
| { | |||
| Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto); | |||
| Task<List<AdApplicantsViewDto>> GetAllAdsApplicants(ApplicantFilterDto applicantFilterDto); | |||
| Task<ApplicantViewDto> GetById(int id); | |||
| Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id); | |||
| Task ApplyForAd(ApplyForAdRequestDto request); | |||
| Task DeleteApplicant(int id); | |||
| Task<List<ApplicantOptionsDTO>> GetOptions(); | |||
| Task<ServiceResponseDTO<object>> InitializeProcess(ApplicantProcessRequestDTO model); | |||
| Task ImportApplicant(List<ApplicantImportDto> request); | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Comment; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface ICommentService | |||
| { | |||
| Task CreateComment(CommentCreateDto commentCreateDto); | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| using Microsoft.AspNetCore.Http; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IImportService | |||
| { | |||
| Task<List<ApplicantImportDto>> Import(IFormFile fileData); | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsuranceCompaniesService | |||
| { | |||
| Task<List<InsuranceCompanyViewDto>> GetInsuranceCompanies(); | |||
| Task<InsuranceCompanyViewDto?> GetInsuranceCompany(long id); | |||
| Task CreateInsuranceCompany(InsuranceCompanyCreateDto insuranceCompanyCreateDto); | |||
| Task UpdateInsuranceCompany(long insuranceCompanyId, InsuranceCompanyUpdateDto insuranceCompanyUpdateDto); | |||
| Task DeleteInsuranceCompany(long insuranceCompanyId); | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsurancePoliciesService | |||
| { | |||
| Task<List<InsurancePolicyViewDto>> GetInsurancePolicies(); | |||
| Task<InsurancePolicyViewDto?> GetInsurancePolicy(long id); | |||
| Task CreateInsurancePolicy(InsurancePolicyCreateDto insurancePolicyCreateDto); | |||
| Task UpdateInsurancePolicy(long insurancePolicyId, InsurancePolicyUpdateDto insurancePolicyUpdateDto); | |||
| Task DeleteInsurancePolicy(long insurancePolicyId); | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IInsurersService | |||
| { | |||
| Task<List<InsurerViewDto>> GetInsurers(); | |||
| Task<InsurerViewDto?> GetInsurer(long id); | |||
| Task CreateInsurer(InsurerCreateDto insurerCreateDto); | |||
| Task UpdateInsurer(long insurerId, InsurerUpdateDto insurerUpdateDto); | |||
| Task DeleteInsurerAsync(long insurerId); | |||
| } | |||
| } | |||
| @@ -1,28 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Pattern; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IPatternService | |||
| { | |||
| Task<List<PatternResponseDto>> GetAllAsync(); | |||
| Task<PatternResponseDto> GetByIdAsync(int id); | |||
| 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); | |||
| } | |||
| } | |||
| @@ -1,7 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface ISaveImportedDataService | |||
| { | |||
| Task<List<ApplicantImportDto>> Save(); | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Schedule; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IScheduleService | |||
| { | |||
| Task<List<ScheduleViewDto>> GetScheduleForCertainPeriod(int month, int year); | |||
| } | |||
| } | |||
| @@ -1,10 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IScreeningTestClientService | |||
| { | |||
| Task<AuthSuccessResponse> LoginToScreening(AuthenticateRequestDto model); | |||
| Task GetScreening(); | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface IScreeningTestService | |||
| { | |||
| Task<BaseResult<IEnumerable<TestMicroserviceRequest>>> GetScreening(); | |||
| Task<bool> SendTest(TestMicroserviceInviteRequest test); | |||
| Task<AuthSuccessResponse> LoginToScreening(); | |||
| } | |||
| } | |||
| @@ -1,16 +0,0 @@ | |||
| | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| using Diligent.WebAPI.Contracts.DTOs.Stats; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface ISelectionLevelService | |||
| { | |||
| Task<List<SelectionLevelResponseWithDataDto>> GetAllAsync(); | |||
| Task<SelectionLevelResposneDto> GetByIdAsync(int id); | |||
| Task<SelectionLevel> GetByIdEntity(int id); | |||
| List<SelectionLevelResponseWithDataDto> GetFilteredLevelsAsync(SelectionProcessFilterDto filters); | |||
| Task<List<SelectionLevelInfoDto>> GetCountByLevels(List<string> statuses); | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| using Diligent.WebAPI.Contracts.DTOs.Stats; | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface ISelectionProcessService | |||
| { | |||
| Task<List<SelectionProcessResposneDto>> GetAllAsync(); | |||
| Task<bool> FinishSelectionProcess(SelectionProcessCreateDto model); | |||
| Task UpdateSelectionProcessStatusAsync(int id, SelectionProcessUpdateStatusDto selectionProcessUpdateStatusDto); | |||
| Task StatusUpdate(StatusChangeDTO model); | |||
| Task InterviewerUpdate(InterviewerUpdateDTO model); | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| | |||
| namespace Diligent.WebAPI.Business.Services.Interfaces | |||
| { | |||
| public interface ITechnologyService | |||
| { | |||
| Task<List<TechnologyResponseDto>> GetAllAsync(); | |||
| Task<TechnologyResponseDto> GetByIdAsync(int id); | |||
| Task<Technology> GetEntityByIdAsync(int id); | |||
| Task<List<Technology>> GetEntitiesAsync(int [] technologiesIds); | |||
| } | |||
| } | |||
| @@ -1,241 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Pattern; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class PatternService : IPatternService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| 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, IEmailer emailer, ISelectionProcessService selectionProcessService) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _selectionLevelService = selectionLevelService; | |||
| _logger = logger; | |||
| _emailer = emailer; | |||
| _selectionProcessService = selectionProcessService; | |||
| } | |||
| public async Task<List<PatternResponseDto>> GetAllAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all Patterns"); | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var fromDb = await _context.Patterns.Include(x => x.SelectionLevel).ToListAsync(); | |||
| _logger.LogInformation($"Received {fromDb.Count} patterns from db."); | |||
| _logger.LogInformation($"Mapping received patterns to PatternResponseDto"); | |||
| var result = _mapper.Map<List<PatternResponseDto>>(fromDb); | |||
| _logger.LogInformation($"Patterns has been mapped and received to client: {result.Count} mapped patterns"); | |||
| return result; | |||
| } | |||
| public async Task<PatternResponseDto> GetByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Pattern with id = {id}"); | |||
| var pattern = await _context.Patterns.Include(x => x.SelectionLevel).Where(x => x.Id == id).FirstOrDefaultAsync(); | |||
| if (pattern is null) | |||
| { | |||
| _logger.LogError($"Pattern with id = {id} not found"); | |||
| throw new EntityNotFoundException("Pattern not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Pattern with id = {id}"); | |||
| PatternResponseDto result = _mapper.Map<PatternResponseDto>(pattern); | |||
| _logger.LogInformation($"Pattern with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<List<PatternResponseDto>> GetFilteredPatternsAsync(FilterPatternDto filterPatternDto) | |||
| { | |||
| _logger.LogInformation($"Start getting all filtered Patterns"); | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var filteredPatterns = await _context.Patterns.Include(x => x.SelectionLevel).ToListAsync(); | |||
| _logger.LogInformation($"Received {filteredPatterns.Count} patterns from db."); | |||
| _logger.LogInformation($"Mapping received patterns to PatternResponseDto"); | |||
| List<PatternResponseDto> result = _mapper.Map<List<PatternResponseDto>>(filteredPatterns.FilterApplicants(filterPatternDto)); | |||
| _logger.LogInformation($"Patterns has been mapped and received to client: {result.Count} mapped patterns"); | |||
| 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"); | |||
| _logger.LogInformation($"Check is Pattern in database"); | |||
| var patternExists = await _context.Patterns.Include(x => x.SelectionLevel).Where(x => x.Title == patternCreateDto.Title && x.SelectionLevelId == patternCreateDto.SelectionLevelId).FirstOrDefaultAsync(); | |||
| if (patternExists is not null) | |||
| { | |||
| _logger.LogError($"Pattern already exists in database"); | |||
| throw new EntityNotFoundException("Pattern already exists in database"); | |||
| } | |||
| _logger.LogInformation($"Pattern is not in database"); | |||
| _logger.LogInformation($"Mapping PatternCreateDto to model"); | |||
| var pattern = _mapper.Map<Pattern>(patternCreateDto); | |||
| _logger.LogInformation($"Pattern mapped successfully"); | |||
| _logger.LogInformation($"Start searching SelectionLevel with id = {patternCreateDto.SelectionLevelId}"); | |||
| var selectionLevel = await _selectionLevelService.GetByIdEntity(patternCreateDto.SelectionLevelId); | |||
| if(selectionLevel == null) | |||
| { | |||
| _logger.LogError($"SelectionLevel with id = {patternCreateDto.SelectionLevelId} not found"); | |||
| throw new EntityNotFoundException("Selection level not found"); | |||
| } | |||
| _logger.LogInformation($"Add founded SelectionLevel to pattern"); | |||
| pattern.SelectionLevel = selectionLevel; | |||
| await _context.AddAsync(pattern); | |||
| _logger.LogInformation($"Saving Ad to db..."); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Saved Ad to db..."); | |||
| 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"); | |||
| _logger.LogInformation($"Check is Pattern in database"); | |||
| var patternExists = await _context.Patterns.Include(x => x.SelectionLevel).Where(x => x.Title == patternUpdateDto.Title && x.SelectionLevelId == patternUpdateDto.SelectionLevelId).FirstOrDefaultAsync(); | |||
| if (patternExists is not null) | |||
| { | |||
| _logger.LogError($"Pattern already exists in database"); | |||
| throw new EntityNotFoundException("Pattern already exists in database"); | |||
| } | |||
| _logger.LogInformation($"Start searching Pattern with id = {id}"); | |||
| var pattern = await _context.Patterns.Where(x => x.Id == id).FirstOrDefaultAsync(); | |||
| if (pattern is null) | |||
| { | |||
| _logger.LogError($"Pattern with id = {id} not found"); | |||
| throw new EntityNotFoundException("Pattern not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Pattern with id = {id}"); | |||
| _mapper.Map(patternUpdateDto, pattern); | |||
| _logger.LogInformation($"Pattern with id = {id} mapped successfully"); | |||
| _logger.LogInformation($"Start searching SelectionLevel with id = {patternUpdateDto.SelectionLevelId}"); | |||
| var selectionLevel = await _selectionLevelService.GetByIdEntity(patternUpdateDto.SelectionLevelId); | |||
| if (selectionLevel == null) | |||
| { | |||
| _logger.LogError($"SelectionLevel with id = {patternUpdateDto.SelectionLevelId} not found"); | |||
| throw new EntityNotFoundException("Selection level not found"); | |||
| } | |||
| _logger.LogInformation($"Add founded SelectionLevel to pattern"); | |||
| pattern.SelectionLevel = selectionLevel; | |||
| _context.Entry(pattern).State = EntityState.Modified; | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Pattern saved to DB"); | |||
| await result; | |||
| } | |||
| public async Task DeleteAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Pattern with id = {id}"); | |||
| var pattern = await _context.Patterns.FindAsync(id); | |||
| if (pattern is null) | |||
| { | |||
| _logger.LogError($"Pattern with id = {id} not found"); | |||
| throw new EntityNotFoundException("Pattern not found"); | |||
| } | |||
| _context.Patterns.Remove(pattern); | |||
| var result = _context.SaveChangesAsync(); | |||
| _logger.LogInformation($"Ad saved to DB"); | |||
| await result; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,91 +0,0 @@ | |||
| using Bytescout.Spreadsheet; | |||
| using System.Globalization; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class SaveImportedDataService : ISaveImportedDataService | |||
| { | |||
| private readonly ILogger<SaveImportedDataService> _logger; | |||
| private readonly IAdService _adService; | |||
| public SaveImportedDataService(ILogger<SaveImportedDataService> logger, IAdService adService) | |||
| { | |||
| _logger = logger; | |||
| _adService = adService; | |||
| } | |||
| public async Task<List<ApplicantImportDto>> Save() | |||
| { | |||
| List<ApplicantImportDto> applicants = new List<ApplicantImportDto>(); | |||
| try | |||
| { | |||
| _logger.LogInformation("Unoirtubg data from file..."); | |||
| var path = Path.Combine(Directory.GetCurrentDirectory(), "Files", "s.xlsx"); | |||
| Spreadsheet document = new Spreadsheet(); | |||
| document.LoadFromFile(path); | |||
| _logger.LogInformation("File is opened successfully"); | |||
| var worksheetsNumber = document.Workbook.Worksheets.Count; | |||
| _logger.LogInformation($"File contains {worksheetsNumber} sheets"); | |||
| for (int k = 0; k < worksheetsNumber; k++) | |||
| { | |||
| var worksheets = document.Workbook.Worksheets[k]; | |||
| var position = worksheets.Name; | |||
| _logger.LogInformation($"Import data for Ad {position}"); | |||
| var ad = await _adService.ImportAsync(new AdCreateDto | |||
| { | |||
| Title = position, | |||
| TechnologiesIds = new(), | |||
| MinimumExperience = 0, | |||
| WorkHour = "FullTime", | |||
| Requirements = "", | |||
| Offer = "", | |||
| KeyResponsibilities = "", | |||
| EmploymentType = position.Contains("praksa") ? "Intership" : "Work", | |||
| CreatedAt = DateTime.Now, | |||
| ExpiredAt = DateTime.Now | |||
| }); | |||
| int i = 2; | |||
| while (true) | |||
| { | |||
| if (String.IsNullOrEmpty(worksheets.Cell(i, 0).ToString())) | |||
| break; | |||
| var name = worksheets.Cell(i, 0).ToString().Split(' '); | |||
| var a = new ApplicantImportDto | |||
| { | |||
| FirstName = name[0], | |||
| LastName = name[1], | |||
| Email = worksheets.Cell(i, 1).ToString(), | |||
| CV = worksheets.Cell(i, 2).ToString(), | |||
| ApplicationChannel = worksheets.Cell(i, 6).ToString(), | |||
| Comment = worksheets.Cell(i, 7).ToString(), | |||
| Position = position, | |||
| Ad = ad, | |||
| TypeOfEmployment = position.Contains("praksa") ? "Praksa" : "Posao" | |||
| }; | |||
| _logger.LogInformation($"Loaded user {a.FirstName} {a.LastName}"); | |||
| try | |||
| { | |||
| string str = worksheets.Cell(i, 3).ToString(); | |||
| if(!string.IsNullOrEmpty(str)) | |||
| a.DateOfApplication = DateTime.ParseExact(str, "dd.MM.yyyy.", CultureInfo.InvariantCulture); | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| _logger.LogError("Incorect date time for this candidate"); | |||
| } | |||
| applicants.Add(a); | |||
| _logger.LogInformation("Candidate added successfully in the list"); | |||
| i++; | |||
| } | |||
| } | |||
| } | |||
| catch (Exception e) | |||
| { | |||
| _logger.LogError(e.Message); | |||
| throw new FileNotFoundException("File is not uploaded!"); | |||
| } | |||
| return applicants; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,33 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Schedule; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class ScheduleService : IScheduleService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ILogger<ScheduleService> _logger; | |||
| public ScheduleService(DatabaseContext context, IMapper mapper,ILogger<ScheduleService> logger) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| } | |||
| public async Task<List<ScheduleViewDto>> GetScheduleForCertainPeriod(int month, int year) | |||
| { | |||
| _logger.LogInformation("Start getting schedule for certain period"); | |||
| _logger.LogInformation("Getting data from DB and filter"); | |||
| var selectionProcessess = await _context.SelectionProcesses | |||
| .Include(c => c.Applicant) | |||
| .Include(c => c.SelectionLevel) | |||
| .Where(k => k.Date != null && k.Date.Value.Month == month && k.Date.Value.Year == year) | |||
| .ToListAsync(); | |||
| _logger.LogInformation($"Got {selectionProcessess.Count} selection processes"); | |||
| _logger.LogInformation($"Return schedule for certain period"); | |||
| return _mapper.Map<List<ScheduleViewDto>>(selectionProcessess); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,174 +0,0 @@ | |||
| using Microsoft.AspNetCore.Mvc; | |||
| using Microsoft.AspNetCore.Mvc.Diagnostics; | |||
| using Microsoft.Extensions.Caching.Memory; | |||
| using System.Net; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class ScreeningTestService : IScreeningTestService | |||
| { | |||
| private readonly ScreeningTestSettings _settings; | |||
| private readonly ILogger<ScreeningTestService> _logger; | |||
| private readonly IMemoryCache _memoryCache; | |||
| public ScreeningTestService(IOptions<ScreeningTestSettings> settings, ILogger<ScreeningTestService> logger, IMemoryCache memoryCache) | |||
| { | |||
| _settings = settings.Value; | |||
| _logger = logger; | |||
| _memoryCache = memoryCache; | |||
| } | |||
| public async Task<BaseResult<IEnumerable<TestMicroserviceRequest>>> GetScreening() | |||
| { | |||
| string token = await GetToken(); | |||
| _logger.LogInformation($"Start calling microservice to get tests request"); | |||
| var httpClient = new HttpClient(); | |||
| var request = new HttpRequestMessage(HttpMethod.Get, _settings.Url + "tests"); | |||
| request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); | |||
| _logger.LogInformation("Initilazing http call to microservice"); | |||
| HttpResponseMessage httpResponseMessage; | |||
| try | |||
| { | |||
| _logger.LogInformation("Calling microservis to get test"); | |||
| httpResponseMessage = httpClient.SendAsync(request).Result; | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| _logger.LogError($"Error in call: {ex.Message}"); | |||
| return new BaseResult<IEnumerable<TestMicroserviceRequest>> | |||
| { | |||
| IsSuccess = false, | |||
| DataObject = new List<TestMicroserviceRequest>() | |||
| }; | |||
| } | |||
| if (httpResponseMessage.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| _logger.LogError("Error: Unauthorized"); | |||
| return new BaseResult<IEnumerable<TestMicroserviceRequest>> | |||
| { | |||
| IsSuccess = false, | |||
| DataObject = new List<TestMicroserviceRequest>() | |||
| }; | |||
| } | |||
| if (httpResponseMessage.StatusCode != HttpStatusCode.OK) | |||
| { | |||
| _logger.LogError("Error"); | |||
| return new BaseResult<IEnumerable<TestMicroserviceRequest>> | |||
| { | |||
| IsSuccess = false, | |||
| DataObject = new List<TestMicroserviceRequest>() | |||
| }; | |||
| } | |||
| var response = httpResponseMessage.Content.ReadAsStringAsync().Result; | |||
| var resultData = JsonConvert.DeserializeObject<IEnumerable<TestMicroserviceRequest>>(response); | |||
| _logger.LogInformation($"Call pass and it received: {resultData.Count()} records"); | |||
| return new BaseResult<IEnumerable<TestMicroserviceRequest>> | |||
| { | |||
| DataObject = resultData | |||
| }; | |||
| } | |||
| private async Task<string> GetToken() | |||
| { | |||
| string token = ""; | |||
| if (_memoryCache.TryGetValue("JWT", out string t)) | |||
| { | |||
| token = t; | |||
| } | |||
| else | |||
| { | |||
| var result = await LoginToScreening(); | |||
| var cacheEntryOptions = new MemoryCacheEntryOptions() | |||
| .SetSlidingExpiration(TimeSpan.FromSeconds(60)) | |||
| .SetAbsoluteExpiration(TimeSpan.FromSeconds(3600)) | |||
| .SetPriority(CacheItemPriority.Normal) | |||
| .SetSize(1024); | |||
| _memoryCache.Set("JWT", result.Token, cacheEntryOptions); | |||
| token = result.Token; | |||
| } | |||
| return token; | |||
| } | |||
| public async Task<AuthSuccessResponse> LoginToScreening() | |||
| { | |||
| _logger.LogInformation($"Start calling microservice to login"); | |||
| var httpClient = new HttpClient(); | |||
| var requestUri = new Uri(string.Format(_settings.Url + "auth")); | |||
| var httpContent = new StringContent(System.Text.Json.JsonSerializer.Serialize(new AuthMicroserviceRequest | |||
| { | |||
| Email = _settings.Email, | |||
| Password = _settings.Password | |||
| }), | |||
| Encoding.UTF8, | |||
| "application/json"); | |||
| var response = await httpClient.PostAsync(requestUri, httpContent); | |||
| var content = await response.Content.ReadAsStringAsync(); | |||
| try | |||
| { | |||
| var result = JsonConvert.DeserializeObject<AuthSuccessResponse>(content); | |||
| var expires = result.Expires.Value - DateTime.Now; | |||
| var cacheEntryOptions = new MemoryCacheEntryOptions() | |||
| .SetSlidingExpiration(TimeSpan.FromSeconds(60)) | |||
| .SetAbsoluteExpiration(expires) | |||
| .SetPriority(CacheItemPriority.Normal) | |||
| .SetSize(1024); | |||
| _memoryCache.Set("JWT", result.Token, cacheEntryOptions); | |||
| _logger.LogInformation($"Call pass and it received: {result}"); | |||
| return result; | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| _logger.LogInformation($"Error in call: "); | |||
| return new AuthSuccessResponse { Token = "" }; | |||
| } | |||
| } | |||
| public async Task<bool> SendTest(TestMicroserviceInviteRequest test) | |||
| { | |||
| string token = await GetToken(); | |||
| _logger.LogInformation($"Start calling microservice to send test request"); | |||
| var httpClient = new HttpClient(); | |||
| var request = new HttpRequestMessage(HttpMethod.Post, _settings.Url + "tests"); | |||
| request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token); | |||
| var httpContent = new StringContent(System.Text.Json.JsonSerializer.Serialize(test), | |||
| Encoding.UTF8, | |||
| "application/json"); | |||
| request.Content = httpContent; | |||
| _logger.LogInformation("Initilazing http call to microservice"); | |||
| HttpResponseMessage httpResponseMessage; | |||
| try | |||
| { | |||
| _logger.LogInformation("Calling microservis to send test"); | |||
| httpResponseMessage = httpClient.SendAsync(request).Result; | |||
| } | |||
| catch (Exception ex) | |||
| { | |||
| _logger.LogError($"Error in call: {ex.Message}"); | |||
| return false; | |||
| } | |||
| if (httpResponseMessage.StatusCode == HttpStatusCode.Unauthorized) | |||
| { | |||
| _logger.LogError("Error: Unauthorized"); | |||
| return false; | |||
| } | |||
| if (httpResponseMessage.StatusCode != HttpStatusCode.OK) | |||
| { | |||
| _logger.LogError("Error"); | |||
| return false; | |||
| } | |||
| _logger.LogInformation($"Call pass"); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,103 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Stats; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class SelectionLevelService : ISelectionLevelService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly ILogger<SelectionLevelService> _logger; | |||
| public SelectionLevelService(DatabaseContext context, IMapper mapper, ILogger<SelectionLevelService> logger) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| } | |||
| public async Task<List<SelectionLevelResponseWithDataDto>> GetAllAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all selection levels"); | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var fromDb = await _context.SelectionLevels | |||
| .Include(sl => sl.SelectionProcesses) | |||
| .ThenInclude(sp => sp.Applicant) | |||
| .Include(sl => sl.SelectionProcesses) | |||
| .ThenInclude(sp => sp.Scheduler) | |||
| .ToListAsync(); | |||
| _logger.LogInformation($"Received {fromDb.Count} levels from db."); | |||
| _logger.LogInformation($"Mapping received ads to SelectionLevelResponseWithDataDto"); | |||
| var result = _mapper.Map<List<SelectionLevelResponseWithDataDto>>(fromDb); | |||
| _logger.LogInformation($"Levels has been mapped and received to client: {result.Count} mapped levels"); | |||
| return result; | |||
| } | |||
| public async Task<SelectionLevelResposneDto> GetByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Level with id = {id}"); | |||
| var sl = await _context.SelectionLevels.FindAsync(id); | |||
| if (sl is null) | |||
| { | |||
| _logger.LogError($"Level with id = {id} not found"); | |||
| throw new EntityNotFoundException("Selection level not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Level with id = {id} to SelectionLevelResposneDto"); | |||
| var result = _mapper.Map<SelectionLevelResposneDto>(sl); | |||
| _logger.LogInformation($"Level with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<SelectionLevel> GetByIdEntity(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Level with id = {id}"); | |||
| var sl = await _context.SelectionLevels.FindAsync(id); | |||
| if (sl is null) | |||
| { | |||
| _logger.LogError($"Level with id = {id} not found"); | |||
| throw new EntityNotFoundException("Selection level not found"); | |||
| } | |||
| _logger.LogInformation($"Level with id = {id} found and returned to client"); | |||
| return sl; | |||
| } | |||
| public List<SelectionLevelResponseWithDataDto> GetFilteredLevelsAsync(SelectionProcessFilterDto filters) | |||
| { | |||
| _logger.LogInformation("Start getting filtered selection levels"); | |||
| _logger.LogInformation("Getting data from DB and filter it"); | |||
| var filteredLevels = _context.SelectionLevels | |||
| .Include(x => x.SelectionProcesses) | |||
| .ThenInclude(sp => sp.Applicant).ToList() | |||
| .FilterLevels(filters); | |||
| _logger.LogInformation($"Received {filteredLevels.Count} levels from db."); | |||
| _logger.LogInformation($"Mapping received ads to SelectionLevelResponseWithDataDto"); | |||
| var result = _mapper.Map<List<SelectionLevelResponseWithDataDto>>(filteredLevels); | |||
| _logger.LogInformation($"Levels has been mapped and received to client: {result.Count} mapped levels"); | |||
| return result; | |||
| } | |||
| public async Task<List<SelectionLevelInfoDto>> GetCountByLevels(List<string> statuses) | |||
| { | |||
| _logger.LogInformation("Start getting all Selection levels"); | |||
| var res = await _context.SelectionLevels.Include(n => n.SelectionProcesses).ToListAsync(); | |||
| _logger.LogInformation($"Received {res.Count} selection levels"); | |||
| _logger.LogInformation("Mapping levels with process counts to SelectionLevelInfo"); | |||
| var resMapped = res.Select(n => new SelectionLevelInfoDto | |||
| { | |||
| Level = n.Name, | |||
| CountAll = n.SelectionProcesses.Count, | |||
| CountDone = n.SelectionProcesses.Where(n => statuses.Contains(n.Status)).Count() | |||
| }).ToList(); | |||
| return resMapped; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,144 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Stats; | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class SelectionProcessService : ISelectionProcessService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly IMapper _mapper; | |||
| private readonly UserManager<User> _userManager; | |||
| private readonly ILogger<SelectionProcessService> _logger; | |||
| public SelectionProcessService(UserManager<User> userManager,DatabaseContext context, IMapper mapper, ILogger<SelectionProcessService> logger) | |||
| { | |||
| _context = context; | |||
| _mapper = mapper; | |||
| _logger = logger; | |||
| _userManager = userManager; | |||
| } | |||
| public async Task<List<SelectionProcessResposneDto>> GetAllAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all Selection Processes"); | |||
| _logger.LogInformation("Getting data from DB"); | |||
| var fromDB = await _context.SelectionProcesses.ToListAsync(); | |||
| _logger.LogInformation($"Received {fromDB.Count} processes from db."); | |||
| _logger.LogInformation($"Mapping received ads to SelectionProcessResposneDto"); | |||
| var result = _mapper.Map<List<SelectionProcessResposneDto>>(fromDB); | |||
| _logger.LogInformation($"Processes has been mapped and received to client: {result.Count} mapped processes"); | |||
| return result; | |||
| } | |||
| public async Task<bool> FinishSelectionProcess(SelectionProcessCreateDto model) | |||
| { | |||
| _logger.LogInformation($"Start finishing selection process with {model.Id}"); | |||
| var sp = await _context.SelectionProcesses.FindAsync(model.Id); | |||
| if (sp is null) | |||
| { | |||
| _logger.LogError($"Process with id = {model.Id} not found"); | |||
| throw new EntityNotFoundException("Selection process not found"); | |||
| } | |||
| _logger.LogInformation($"Changing status for {model.Id}"); | |||
| sp.Status = "Odrađen"; | |||
| _logger.LogInformation($"Skipping throught levels to come to next level"); | |||
| if (sp.SelectionLevelId == _context.SelectionLevels.OrderBy(n => n.Id).Last().Id) | |||
| { | |||
| _logger.LogError($"Applicant is in the last selection level"); | |||
| throw new EntityNotFoundException("Candidate came to the last selection level"); | |||
| } | |||
| var nextLevel = _context.SelectionLevels.AsEnumerable() | |||
| .SkipWhile(obj => obj.Id != sp.SelectionLevelId) | |||
| .Skip(1).First(); | |||
| SelectionProcess newProcess = new SelectionProcess | |||
| { | |||
| Name = model.Name, | |||
| SelectionLevelId = nextLevel.Id, | |||
| Status = "Čeka na zakazivanje", | |||
| ApplicantId = sp.ApplicantId | |||
| }; | |||
| _context.SelectionProcesses.Add(newProcess); | |||
| _logger.LogInformation($"Create and add new selection process"); | |||
| var result = await _context.SaveChangesAsync() > 0; | |||
| _logger.LogInformation($"Saved changes to db"); | |||
| return result; | |||
| } | |||
| 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; | |||
| } | |||
| public async Task StatusUpdate(StatusChangeDTO model) | |||
| { | |||
| _logger.LogInformation($"Start searching process with id = {model.ProcessId}"); | |||
| var process = await _context.SelectionProcesses.FindAsync(model.ProcessId); | |||
| if (process is null) | |||
| { | |||
| _logger.LogError($"Process with id = {model.ProcessId} not found"); | |||
| throw new EntityNotFoundException("Process does not exist."); | |||
| } | |||
| _logger.LogInformation($"Check which status is going to be set."); | |||
| if (model.NewStatus == "Zakazan" && model.SchedulerId is not null) | |||
| { | |||
| _logger.LogInformation($"Start searching user with id = {model.SchedulerId}"); | |||
| var user = await _userManager.FindByIdAsync(model.SchedulerId.ToString()); | |||
| if (user is null) | |||
| throw new EntityNotFoundException("Scheduler does not exist."); | |||
| _logger.LogInformation($"Setting user {user.FirstName} {user.LastName} as scheduler for process with id = {model.ProcessId}"); | |||
| process.SchedulerId = user.Id; | |||
| } | |||
| process.Status = model.NewStatus; | |||
| process.Date = model.Appointment; | |||
| process.Comment = model.Comment; | |||
| _logger.LogInformation($"Processing changes."); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| public async Task InterviewerUpdate(InterviewerUpdateDTO model) | |||
| { | |||
| _logger.LogInformation($"Start searching process with id = {model.ProcessId}"); | |||
| var process = await _context.SelectionProcesses.FindAsync(model.ProcessId); | |||
| if (process is null) | |||
| throw new EntityNotFoundException("Process does not exist."); | |||
| _logger.LogInformation($"Start searching user with id = {model.SchedulerId}"); | |||
| var user = await _userManager.FindByIdAsync(model.SchedulerId.ToString()); | |||
| if (user is null) | |||
| throw new EntityNotFoundException("Scheduler does not exist."); | |||
| _logger.LogInformation($"Setting user {user.FirstName} {user.LastName} as scheduler for process with id = {model.ProcessId}"); | |||
| process.SchedulerId = user.Id; | |||
| _logger.LogInformation("Processing changes..."); | |||
| await _context.SaveChangesAsync(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,66 +0,0 @@ | |||
| namespace Diligent.WebAPI.Business.Services | |||
| { | |||
| public class TechnologyService : ITechnologyService | |||
| { | |||
| private readonly DatabaseContext _context; | |||
| private readonly ILogger<TechnologyService> _logger; | |||
| private readonly IMapper _mapper; | |||
| public TechnologyService(IMapper mapper, DatabaseContext context, ILogger<TechnologyService> logger) | |||
| { | |||
| _mapper = mapper; | |||
| _context = context; | |||
| _logger = logger; | |||
| } | |||
| public async Task<List<TechnologyResponseDto>> GetAllAsync() | |||
| { | |||
| _logger.LogInformation("Start getting all technologies"); | |||
| var technologies = await _context.Technologies.ToListAsync(); | |||
| _logger.LogInformation($"Received {technologies.Count} technologies from database"); | |||
| _logger.LogInformation("Mapping received technologies to TechnologyResponseDto"); | |||
| var technologiesDto = _mapper.Map<List<TechnologyResponseDto>>(technologies); | |||
| _logger.LogInformation($"Technologies mapped successfully"); | |||
| return technologiesDto; | |||
| } | |||
| public async Task<TechnologyResponseDto> GetByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Techology with id = {id}"); | |||
| var technology = await _context.Technologies.FindAsync(id); | |||
| if (technology is null) | |||
| { | |||
| _logger.LogError($"Technology with id = {id} not found"); | |||
| throw new EntityNotFoundException("Technology not found"); | |||
| } | |||
| _logger.LogInformation($"Mapping Technology with id = {id}"); | |||
| var result = _mapper.Map<TechnologyResponseDto>(technology); | |||
| _logger.LogInformation($"Technology with id = {id} mapped successfully"); | |||
| return result; | |||
| } | |||
| public async Task<Technology> GetEntityByIdAsync(int id) | |||
| { | |||
| _logger.LogInformation($"Start searching Ad with id = {id}"); | |||
| var technology = await _context.Technologies.FindAsync(id); | |||
| if (technology is null) | |||
| { | |||
| _logger.LogError($"Technology with id = {id} not found"); | |||
| throw new EntityNotFoundException("Technology not found"); | |||
| } | |||
| _logger.LogInformation($"Technology with id = {id} found successfully"); | |||
| return technology; | |||
| } | |||
| public async Task<List<Technology>> GetEntitiesAsync(int[] technologiesIds) | |||
| { | |||
| _logger.LogInformation("Start getting all technologies"); | |||
| var technologies = await _context.Technologies.Where(x => technologiesIds.Contains(x.TechnologyId)).ToListAsync(); | |||
| _logger.LogInformation($"Received {technologies.Count} technologies from database"); | |||
| return technologies; | |||
| } | |||
| } | |||
| } | |||
| @@ -5,22 +5,13 @@ global using Diligent.WebAPI.Business.Helper; | |||
| global using Diligent.WebAPI.Data; | |||
| global using Diligent.WebAPI.Data.Entities; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsuranceCompany; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsurancePolicy; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Insurer; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookDefinition; | |||
| global using Diligent.WebAPI.Contracts.DTOs.WebhookSubscription; | |||
| global using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Ad; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Auth; | |||
| global using Diligent.WebAPI.Contracts.DTOs.User; | |||
| global using Diligent.WebAPI.Contracts.DTOs; | |||
| global using Diligent.WebAPI.Contracts.Exceptions; | |||
| global using Diligent.WebAPI.Contracts.Models; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| global using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| global using Diligent.WebAPI.Contracts.DTOs.Comment; | |||
| global using Diligent.WebAPI.Business.Extensions; | |||
| global using Microsoft.EntityFrameworkCore; | |||
| @@ -1,12 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdApplicantsViewDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public List<AdApplicantViewDto> Applicants { get; set; } | |||
| public int NubmerOfApplicants { get { return Applicants.Count; } } | |||
| } | |||
| } | |||
| @@ -1,31 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdCreateDto | |||
| { | |||
| public string Title { get; set; } | |||
| public int MinimumExperience { get; set; } | |||
| public DateTime CreatedAt { get; set; } | |||
| public DateTime ExpiredAt { get; set; } | |||
| public string KeyResponsibilities { get; set; } | |||
| public string Requirements { get; set; } | |||
| public string Offer { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| public List<int> TechnologiesIds { get; set; } | |||
| } | |||
| } | |||
| @@ -1,40 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdDetailsResponseDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public int MinimumExperience { get; set; } | |||
| public DateTime CreatedAt { get; set; } | |||
| public DateTime ExpiredAt { get; set; } | |||
| public string KeyResponsibilities { get; set; } | |||
| public string Requirements { get; set; } | |||
| public string Offer { get; set; } | |||
| public int TotalApplicants { get { return CalculateTotalApplicants(); } } | |||
| public List<TechnologyResponseDto> Technologies { get; set; } | |||
| public List<ApplicantViewDto> Applicants { get; set; } | |||
| private int CalculateTotalApplicants() | |||
| { | |||
| return Applicants.Count; | |||
| } | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdFilterDto | |||
| { | |||
| public int MinExperience { get; set; } | |||
| public int MaxExperience { get; set; } | |||
| public string[]? Technologies { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -1,34 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdResponseDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public int MinimumExperience { get; set; } | |||
| public DateTime CreatedAt { get; set; } | |||
| public DateTime ExpiredAt { get; set; } | |||
| public string KeyResponsibilities { get; set; } | |||
| public string Requirements { get; set; } | |||
| public string Offer { get; set; } | |||
| public List<TechnologyResponseDto> Technologies { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdResponseWithCountDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public int MinimumExperience { get; set; } | |||
| public DateTime CreatedAt { get; set; } | |||
| public DateTime ExpiredAt { get; set; } | |||
| public int Count { get; set; } | |||
| } | |||
| } | |||
| @@ -1,29 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class AdUpdateDto | |||
| { | |||
| public string Title { get; set; } | |||
| public int MinimumExperience { get; set; } | |||
| public DateTime CreatedAt { get; set; } | |||
| public DateTime ExpiredAt { get; set; } | |||
| public string KeyResponsibilities { get; set; } | |||
| public string Requirements { get; set; } | |||
| public string Offer { get; set; } | |||
| public string WorkHour { get; set; } | |||
| public string EmploymentType { get; set; } | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Ad | |||
| { | |||
| public class SelectionProcessFilterDto | |||
| { | |||
| public string[]? Statuses { get; set; } | |||
| public DateTime? DateStart { get; set; } | |||
| public DateTime? DateEnd { get; set; } | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class AdApplicantViewDto | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfApplication { get; set; } | |||
| public string CV { get; set; } | |||
| public int Experience { get; set; } | |||
| public List<TechnologyViewDto> TechnologyApplicants { get; set; } = new(); | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantOptionsDTO | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.Models; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantFilterDto : Pagination | |||
| { | |||
| public int MinExperience { get; set; } | |||
| public int MaxExperience { get; set; } | |||
| public string[]? Technologies { get; set; } | |||
| public string? EmploymentType { get; set; } | |||
| public DateTime? MinDateOfApplication { get; set; } | |||
| public DateTime? MaxDateOfApplication { get; set; } | |||
| } | |||
| } | |||
| @@ -1,21 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantImportDto | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public string Position { get; set; } | |||
| public string CV { get; set; } | |||
| public DateTime DateOfApplication { get; set; } | |||
| public string Email { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string LinkedlnLink { get; set; } | |||
| public string GithubLink { get; set; } | |||
| public string BitBucketLink { get; set; } | |||
| public int Experience { get; set; } | |||
| public string ApplicationChannel { get; set; } | |||
| public string TypeOfEmployment { get; set; } | |||
| public string Comment { get; set; } | |||
| public Diligent.WebAPI.Data.Entities.Ad Ad { get; set; } | |||
| } | |||
| } | |||
| @@ -1,10 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantProcessRequestDTO | |||
| { | |||
| [Required] | |||
| public int ApplicantId { get; set; } | |||
| public int? SchedulerId { get; set; } | |||
| public DateTime? Appointment { get; set; } | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantScheduleViewDto | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| } | |||
| } | |||
| @@ -1,31 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Ad; | |||
| using Diligent.WebAPI.Contracts.DTOs.Comment; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| using Diligent.WebAPI.Contracts.DTOs.Technology; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplicantViewDto | |||
| { | |||
| public int ApplicantId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public string Position { get; set; } | |||
| public DateTime DateOfApplication { get; set; } | |||
| public string CV { get; set; } | |||
| public string Email { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string LinkedlnLink { get; set; } | |||
| public string GithubLink { get; set; } | |||
| public string BitBucketLink { get; set; } | |||
| public int Experience { get; set; } | |||
| public string ApplicationChannel { get; set; } | |||
| public string TypeOfEmployment { get; set; } | |||
| public string Gender { get; set; } | |||
| public string ProfessionalQualification { get; set; } | |||
| public List<TechnologyViewDto> TechnologyApplicants { get; set; } = new(); | |||
| public List<CommentViewDto> Comments { get; set; } | |||
| public List<AdResponseDto> Ads { get; set; } | |||
| public List<SelectionProcessResposneWithoutApplicantDto> SelectionProcesses { get; set; } | |||
| } | |||
| } | |||
| @@ -1,40 +0,0 @@ | |||
| using Microsoft.AspNetCore.Http; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Applicant | |||
| { | |||
| public class ApplyForAdRequestDto | |||
| { | |||
| public int AdId { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public int[] TechnologiesIds { get; set; } | |||
| public int Experience { get; set; } | |||
| public string LinkedinLink { get; set; } | |||
| public string GithubLink { get; set; } | |||
| public string BitBucketLink { get; set; } | |||
| public string Email { get; set; } | |||
| public string CoverLetter { get; set; } | |||
| public IFormFile PdfFile { get; set; } | |||
| public string Gender { get; set; } | |||
| public string ProfessionalQualification { get; set; } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| 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; } | |||
| } | |||
| } | |||
| @@ -1,10 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Comment | |||
| { | |||
| public class CommentCreateDto | |||
| { | |||
| public string Content { get; set; } | |||
| public int UserId { get; set; } | |||
| public int ApplicantId { get; set; } | |||
| public List<string> UsersToNotify { get; set; } //email | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.User; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Comment | |||
| { | |||
| public class CommentViewDto | |||
| { | |||
| public string Content { get; set; } | |||
| public DateTime DateOfSending { get; set; } | |||
| public UserResponseDTO User { get; set; } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyCreateDto | |||
| { | |||
| [Required] | |||
| public string Name { get; set; } | |||
| [DataType(DataType.PhoneNumber)] | |||
| [RegularExpression(@"^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$", ErrorMessage = "Not a valid phone number")] | |||
| public string? PhoneNumber { get; set; } | |||
| public string? Fax { get; set; } | |||
| public string? City { get; set; } | |||
| public string? Country { get; set; } | |||
| [RegularExpression(@"^\d{5}(-\d{4})?$", ErrorMessage = "Invalid Postal Code")] | |||
| public string? PostalCode { get; set; } | |||
| public string? LegalAddress { get; set; } | |||
| [RegularExpression(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$", ErrorMessage = "Invalid email address")] | |||
| public string? LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyUpdateDto | |||
| { | |||
| public string Name { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string Fax { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string LegalAddress { get; set; } | |||
| public string LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsuranceCompany | |||
| { | |||
| public class InsuranceCompanyViewDto | |||
| { | |||
| public long Id { get; set; } | |||
| public DateTime CreatedAtUtc { get; set; } | |||
| public DateTime? UpdatedAtUtc { get; set; } | |||
| public DateTime? DeletedAtUtc { get; set; } | |||
| public string Name { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string Fax { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string LegalAddress { get; set; } | |||
| public string LegalEmail { get; set; } | |||
| } | |||
| } | |||
| @@ -1,10 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyCreateDto | |||
| { | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyUpdateDto | |||
| { | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.InsurancePolicy | |||
| { | |||
| public class InsurancePolicyViewDto | |||
| { | |||
| public int Id { get; set; } | |||
| public decimal Premium { get; set; } | |||
| public DateTime StartDate { get; set; } | |||
| public DateTime EndDate { get; set; } | |||
| public string Type { get; set; } | |||
| //public long InsurerId { get; set; } | |||
| //public virtual Insurer Insurer { get; set; } | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerCreateDto | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public long InsuranceCompanyId { get; set; } | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerUpdateDto | |||
| { | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public long InsuranceCompanyId { get; set; } | |||
| } | |||
| } | |||
| @@ -1,18 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Insurer | |||
| { | |||
| public class InsurerViewDto | |||
| { | |||
| public long Id { get; set; } | |||
| public string FirstName { get; set; } | |||
| public string LastName { get; set; } | |||
| public DateTime DateOfBirth { get; set; } | |||
| public string PhoneNumber { get; set; } | |||
| public string City { get; set; } | |||
| public string Country { get; set; } | |||
| public string PostalCode { get; set; } | |||
| public string Address { get; set; } | |||
| public string Email { get; set; } | |||
| public InsuranceCompanyViewDto InsuranceCompany { get; set; } | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class FilterPatternDto | |||
| { | |||
| public DateTime? FromDate { get; set; } | |||
| public DateTime? ToDate { get; set; } | |||
| public int[]? SelectionLevels { get; set; } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class PatternCreateDto | |||
| { | |||
| public string Title { get; set; } | |||
| public DateTime? CreatedAt { get; set; } = DateTime.Now; | |||
| public int SelectionLevelId { get; set; } | |||
| public string Message { get; set; } | |||
| } | |||
| } | |||
| @@ -1,22 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class PatternResponseDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Title { get; set; } | |||
| public DateTime CreatedAt { get; set; } = DateTime.Now; | |||
| public SelectionLevelResposneDto SelectionLevel { get; set; } | |||
| public string Message { get; set; } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Pattern | |||
| { | |||
| public class PatternUpdateDto | |||
| { | |||
| public string Title { get; set; } | |||
| public DateTime CreatedAt { get; set; } = DateTime.Now; | |||
| public int SelectionLevelId { get; set; } | |||
| public string Message { get; set; } | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| 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; } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| 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; } | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Schedule | |||
| { | |||
| public class ScheduleViewDto | |||
| { | |||
| public DateTime? Date { get; set; } | |||
| public string? Link { get; set; } | |||
| public SelectionLevelResposneDto SelectionLevel { get; set; } | |||
| public ApplicantScheduleViewDto Applicant { get; set; } | |||
| } | |||
| } | |||
| @@ -1,11 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionProcess; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionLevel | |||
| { | |||
| public class SelectionLevelResponseWithDataDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Name { get; set; } | |||
| public List<SelectionProcessResposneDto> SelectionProcesses { get; set; } | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionLevel | |||
| { | |||
| public class SelectionLevelResposneDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Name { get; set; } | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class InterviewerUpdateDTO { | |||
| [Required] | |||
| public int ProcessId { get; set; } | |||
| [Required] | |||
| public int SchedulerId { get; set; } | |||
| } | |||
| } | |||
| @@ -1,14 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class SelectionProcessCreateDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string? Name { get; set; } | |||
| public string? Status { get; set; } | |||
| public DateTime? Date { get; set; } | |||
| public string? Link { get; set; } | |||
| public int SchedulerId { get; set; } | |||
| public int SelectionLevelId { get; set; } | |||
| public int ApplicantId { get; set; } | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.Applicant; | |||
| using Diligent.WebAPI.Contracts.DTOs.User; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class SelectionProcessResposneDto | |||
| { | |||
| public int Id { get; set; } | |||
| public string Name { get; set; } | |||
| public string Status { get; set; } | |||
| public DateTime? Date { get; set; } | |||
| public string? Link { get; set; } | |||
| public ApplicantViewDto Applicant { get; set; } | |||
| public UserResponseDTO Scheduler { get; set; } | |||
| public int SelectionLevelId { get; set; } | |||
| } | |||
| } | |||
| @@ -1,15 +0,0 @@ | |||
| using Diligent.WebAPI.Contracts.DTOs.SelectionLevel; | |||
| using Diligent.WebAPI.Contracts.DTOs.User; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class SelectionProcessResposneWithoutApplicantDto | |||
| { | |||
| public string Status { get; set; } | |||
| public DateTime? Date { get; set; } | |||
| public string? Link { get; set; } | |||
| public string? Comment { get; set; } | |||
| public UserResponseDTO Scheduler { get; set; } | |||
| public SelectionLevelResposneDto SelectionLevel { get; set; } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| 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; } | |||
| } | |||
| } | |||
| @@ -1,19 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.SelectionProcess | |||
| { | |||
| public class StatusChangeDTO | |||
| { | |||
| [Required] | |||
| public string NewStatus { get; set; } | |||
| [Required] | |||
| public int ProcessId { get; set; } | |||
| public int? SchedulerId { get; set; } | |||
| public DateTime? Appointment { get; set; } | |||
| public string? Comment { get; set; } | |||
| } | |||
| } | |||
| @@ -1,9 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Stats | |||
| { | |||
| public class SelectionLevelInfoDto | |||
| { | |||
| public string Level { get; set; } | |||
| public int CountAll { get; set; } | |||
| public int CountDone { get; set; } | |||
| } | |||
| } | |||
| @@ -1,7 +0,0 @@ | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Technology | |||
| { | |||
| public class TechnologyApplicantViewDto | |||
| { | |||
| public TechnologyResponseDto Technology { get; set; } | |||
| } | |||
| } | |||
| @@ -1,17 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Technology | |||
| { | |||
| public class TechnologyResponseDto | |||
| { | |||
| public int TechnologyId { get; set; } | |||
| public string TechnologyType { get; set; } | |||
| public string Name { get; set; } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Contracts.DTOs.Technology | |||
| { | |||
| public class TechnologyViewDto | |||
| { | |||
| public TechnologyResponseDto Technology { get; set; } | |||
| } | |||
| } | |||
| @@ -1,3 +1,2 @@ | |||
| global using System.Net; | |||
| global using Diligent.WebAPI.Contracts.DTOs.InsuranceCompany; | |||
| global using System.ComponentModel.DataAnnotations; | |||
| @@ -1,18 +0,0 @@ | |||
| using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| namespace Diligent.WebAPI.Data.Configurations | |||
| { | |||
| public class AdConfiguration : IEntityTypeConfiguration<Ad> | |||
| { | |||
| public void Configure(EntityTypeBuilder<Ad> builder) | |||
| { | |||
| builder.Property(c => c.WorkHour).HasConversion<string>(); | |||
| builder.Property(c => c.EmploymentType).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,25 +0,0 @@ | |||
| using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
| namespace Diligent.WebAPI.Data.Configurations | |||
| { | |||
| public class ApplicantConfiguration : IEntityTypeConfiguration<Applicant> | |||
| { | |||
| public void Configure(EntityTypeBuilder<Applicant> builder) | |||
| { | |||
| builder.Property(c => c.FirstName).HasMaxLength(128); | |||
| builder.Property(c => c.LastName).HasMaxLength(128); | |||
| builder.Property(c => c.LastName).HasMaxLength(128); | |||
| builder.Property(c => c.Position).HasMaxLength(128); | |||
| builder.Property(c => c.ProfessionalQualification).HasMaxLength(128); | |||
| builder.Property(c => c.CV).IsRequired(true); | |||
| builder.Property(c => c.Email).HasMaxLength(128); | |||
| builder.Property(c => c.PhoneNumber).HasMaxLength(30); | |||
| builder.Property(c => c.LinkedlnLink).IsRequired(false); | |||
| builder.Property(c => c.GithubLink).IsRequired(false); | |||
| builder.Property(c => c.BitBucketLink).IsRequired(false); | |||
| builder.Property(c => c.ApplicationChannel).IsRequired(false); | |||
| builder.Property(c => c.TypeOfEmployment).IsRequired(true).HasConversion<string>(); | |||
| builder.Property(c => c.Gender).IsRequired(true).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,12 +0,0 @@ | |||
| using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
| namespace Diligent.WebAPI.Data.Configurations | |||
| { | |||
| public class CommentConfiguration : IEntityTypeConfiguration<Comment> | |||
| { | |||
| public void Configure(EntityTypeBuilder<Comment> builder) | |||
| { | |||
| builder.Property(c => c.Content).HasMaxLength(1024); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,13 +0,0 @@ | |||
| using Microsoft.EntityFrameworkCore.Metadata.Builders; | |||
| namespace Diligent.WebAPI.Data.Configurations | |||
| { | |||
| public class TechnologyConfiguration : IEntityTypeConfiguration<Technology> | |||
| { | |||
| public void Configure(EntityTypeBuilder<Technology> builder) | |||
| { | |||
| builder.Property(c => c.Name).HasMaxLength(128); | |||
| builder.Property(c => c.TechnologyType).HasConversion<string>(); | |||
| } | |||
| } | |||
| } | |||
| @@ -37,7 +37,7 @@ namespace Diligent.WebAPI.Data | |||
| using var scope = serviceProvider.CreateScope(); | |||
| var databaseContext = scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | |||
| if(!databaseContext.Tags.Any()) | |||
| if (!databaseContext.Tags.Any()) | |||
| { | |||
| var tags = new List<Tag> | |||
| { | |||
| @@ -4,20 +4,9 @@ namespace Diligent.WebAPI.Data; | |||
| public class DatabaseContext : IdentityDbContext<User, AppRole, int> | |||
| { | |||
| public DbSet<InsuranceCompany> InsuranceCompanies { get; set; } | |||
| public DbSet<Insurer> Insurers { get; set; } | |||
| public DbSet<InsurancePolicy> InsurancePolicies { get; set; } | |||
| public DbSet<WebhookSubscription> WebhookSubscriptions { get; set; } | |||
| public DbSet<WebhookDefinition> WebhookDefinitions { get; set; } | |||
| public DbSet<RefreshToken> RefreshTokens { get; set; } | |||
| public DbSet<Ad> Ads { get; set; } | |||
| public DbSet<Applicant> Applicants { get; set; } | |||
| public DbSet<Technology> Technologies { get; set; } | |||
| public DbSet<TechnologyApplicant> ApplicantTechnologies { get; set; } | |||
| public DbSet<Comment> Comments { get; set; } | |||
| public DbSet<SelectionLevel> SelectionLevels { get; set; } | |||
| public DbSet<SelectionProcess> SelectionProcesses { get; set; } | |||
| public DbSet<Pattern> Patterns { get; set; } | |||
| public DbSet<FileEntity> Files { get; set; } | |||
| public DbSet<Category> Categories { get; set; } | |||
| public DbSet<Tag> Tags { get; set; } | |||
| @@ -29,23 +18,6 @@ public class DatabaseContext : IdentityDbContext<User, AppRole, int> | |||
| protected override void OnModelCreating(ModelBuilder modelBuilder) | |||
| { | |||
| base.OnModelCreating(modelBuilder); | |||
| modelBuilder.Entity<SelectionLevel>().HasData( | |||
| new List<SelectionLevel>{ | |||
| new SelectionLevel{ Id = 1, Name = "HR intervju"}, | |||
| new SelectionLevel{ Id = 2, Name = "Screening test"}, | |||
| new SelectionLevel{ Id = 3, Name = "Tehnicki intervju"}, | |||
| new SelectionLevel{ Id = 4, Name = "Konacna odluka"}, | |||
| }); | |||
| modelBuilder.ApplyConfiguration(new ApplicantConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new TechnologyConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new CommentConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new UserConfiguration()); | |||
| modelBuilder.ApplyConfiguration(new AdConfiguration()); | |||
| modelBuilder | |||
| .Entity<User>() | |||
| .HasMany(user => user.Processes) | |||
| .WithOne(process => process.Scheduler) | |||
| .OnDelete(DeleteBehavior.SetNull); | |||
| } | |||
| } | |||