You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ApplicantService.cs 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. using Azure.Storage.Blobs;
  2. using Microsoft.Extensions.Configuration;
  3. using Microsoft.WindowsAzure.Storage;
  4. using Microsoft.WindowsAzure.Storage.Blob;
  5. using static Diligent.WebAPI.Data.Entities.Applicant;
  6. namespace Diligent.WebAPI.Business.Services
  7. {
  8. public class ApplicantService : IApplicantService
  9. {
  10. private readonly DatabaseContext _context;
  11. private readonly IMapper _mapper;
  12. private readonly ILogger<ApplicantService> _logger;
  13. private readonly IUserService _userService;
  14. private readonly IConfiguration _configuration;
  15. public ApplicantService(DatabaseContext context, IMapper mapper, ILogger<ApplicantService> logger,
  16. IUserService userService,IConfiguration configuration)
  17. {
  18. _context = context;
  19. _mapper = mapper;
  20. _logger = logger;
  21. _userService = userService;
  22. _configuration = configuration;
  23. }
  24. public ApplicantService(DatabaseContext context, IMapper mapper, ILogger<ApplicantService> logger)
  25. {
  26. _context = context;
  27. _mapper = mapper;
  28. _logger = logger;
  29. }
  30. public async Task<QueryResultDto<ApplicantViewDto>> GetFilteredApplicants(ApplicantFilterDto applicantFilterDto)
  31. {
  32. _logger.LogInformation("Start getting filtered applicants");
  33. _logger.LogInformation("Getting data from DB and filter");
  34. var filteredApplicants = (await _context.Applicants
  35. .Include(c => c.Ads)
  36. .Include(x => x.TechnologyApplicants)
  37. .ThenInclude(x => x.Technology).ToListAsync())
  38. .FilterApplicants(applicantFilterDto);
  39. int totalNumberOfItems = filteredApplicants.Count;
  40. _logger.LogInformation($"Got {totalNumberOfItems} applicants");
  41. filteredApplicants = PaginationExtension.ApplyPagging(filteredApplicants, new Pagination
  42. {
  43. CurrentPage = applicantFilterDto.CurrentPage,
  44. PageSize = applicantFilterDto.PageSize
  45. });
  46. _logger.LogInformation($"Return list of applicants");
  47. return new QueryResultDto<ApplicantViewDto>
  48. {
  49. Items = _mapper.Map<List<ApplicantViewDto>>(filteredApplicants),
  50. Total = totalNumberOfItems
  51. };
  52. }
  53. public async Task<ApplicantViewDto> GetById(int id)
  54. {
  55. _logger.LogInformation($"Start searching Applicant with id = {id}");
  56. var applicant = await _context.Applicants
  57. .Include(x => x.Ads)
  58. .ThenInclude(x => x.Technologies)
  59. .Include(x => x.TechnologyApplicants)
  60. .ThenInclude(x => x.Technology)
  61. .Include(x => x.Comments)
  62. .ThenInclude(t => t.User)
  63. .FirstOrDefaultAsync(x => x.ApplicantId == id);
  64. if (applicant is null)
  65. {
  66. _logger.LogError($"Applicant with id = {id} not found");
  67. throw new EntityNotFoundException("Applicant not found");
  68. }
  69. _logger.LogInformation($"Mapping Applicant with id = {id}");
  70. var result = _mapper.Map<ApplicantViewDto>(applicant);
  71. _logger.LogInformation($"Applicant with id = {id} mapped successfully");
  72. return result;
  73. }
  74. public async Task<ApplicantViewDto> GetApplicantWithSelectionProcessesById(int id)
  75. {
  76. var applicant = await _context.Applicants
  77. .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.SelectionLevel)
  78. .Include(a => a.SelectionProcesses).ThenInclude(sp => sp.Scheduler)
  79. .FirstOrDefaultAsync(a => a.ApplicantId == id);
  80. if (applicant is null)
  81. throw new EntityNotFoundException("Applicant not found");
  82. return _mapper.Map<ApplicantViewDto>(applicant);
  83. }
  84. public async Task DeleteApplicant(int id)
  85. {
  86. _logger.LogInformation($"Start searching Applicant with id = {id}");
  87. var applicant = await _context.Applicants.FindAsync(id);
  88. if (applicant is null)
  89. {
  90. _logger.LogError($"Applicant with id = {id} not found");
  91. throw new EntityNotFoundException("Applicant not found");
  92. }
  93. _logger.LogInformation($"Removing Applicant with id = {id}");
  94. _context.Applicants.Remove(applicant);
  95. var result = _context.SaveChangesAsync();
  96. _logger.LogInformation($"Applicant with id = {id} is removed successfully");
  97. await result;
  98. }
  99. public async Task<List<AdApplicantsViewDto>> GetAllAdsApplicants(ApplicantFilterDto applicantFilterDto)
  100. {
  101. _logger.LogInformation("Start getting filtered applicants");
  102. _logger.LogInformation("Getting data from DB and filter");
  103. var adsApplicants = (await _context.Ads
  104. .Include(a => a.Applicants)
  105. .ThenInclude(a => a.TechnologyApplicants)
  106. .ThenInclude(a => a.Technology)
  107. .ToListAsync())
  108. .FilterAdApplicants(applicantFilterDto);
  109. _logger.LogInformation($"Got {adsApplicants.Count} ads");
  110. var result = _mapper.Map<List<AdApplicantsViewDto>>(adsApplicants);
  111. return result;
  112. }
  113. public async Task ApplyForAd(ApplyForAdRequestDto request)
  114. {
  115. string fileName = string.Format(@"{0}.pdf", DateTime.Now.Ticks);
  116. string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
  117. CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
  118. CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
  119. CloudBlobContainer container = blobClient.GetContainerReference(
  120. _configuration.GetValue<string>("BlobContainerName"));
  121. CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
  122. await using (var data = request.PdfFile.OpenReadStream())
  123. {
  124. await blockBlob.UploadFromStreamAsync(data);
  125. }
  126. _logger.LogInformation("Start applying for ad");
  127. _logger.LogInformation("Find ad by id");
  128. var ad = await _context.Ads.Where(x => x.Id == request.AdId).FirstOrDefaultAsync();
  129. if (ad == null)
  130. {
  131. _logger.LogError($"Ad with {request.AdId} not found");
  132. throw new EntityNotFoundException("Ad not found in database");
  133. }
  134. _logger.LogInformation($"Find sent technologies from FE in database");
  135. var technologies = await _context.Technologies.Where(x => request.TechnologiesIds.Contains(x.TechnologyId)).ToListAsync();
  136. _logger.LogInformation($"Create applicant instance with sent data");
  137. Applicant applicant = new()
  138. {
  139. FirstName = request.FirstName,
  140. LastName = request.LastName,
  141. Position = ad.Title,
  142. DateOfApplication = DateTime.UtcNow,
  143. CV = fileName,
  144. Email = request.Email,
  145. PhoneNumber = request.PhoneNumber,
  146. GithubLink = request.GithubLink,
  147. LinkedlnLink = request.LinkedinLink,
  148. BitBucketLink = request.BitBucketLink,
  149. Experience = request.Experience,
  150. //TypeOfEmployment = (EmploymentTypes)Enum.Parse(typeof(EmploymentTypes), ad.EmploymentType, true),
  151. TypeOfEmployment = ad.EmploymentType == EmploymentTypes.Intership ? TypesOfEmployment.Intership : TypesOfEmployment.Posao,
  152. Comments = new(),
  153. Ads = new List<Ad> { ad },
  154. SelectionProcesses = new(),
  155. TechnologyApplicants = new(),
  156. ApplicationChannel = "Putem sajta"
  157. };
  158. _logger.LogInformation($"Saving applicant in database");
  159. await _context.Applicants.AddAsync(applicant);
  160. var res = await _context.SaveChangesAsync();
  161. _logger.LogInformation($"Applicant saved in database");
  162. _logger.LogInformation($"Saving TechnologyApplicants in database");
  163. for (int i = 0; i < technologies.Count; i++)
  164. {
  165. await _context.ApplicantTechnologies.AddAsync(new TechnologyApplicant { Applicant = applicant, ApplicantId = applicant.ApplicantId, Technology = technologies[i], TechnologyId = technologies[i].TechnologyId });
  166. }
  167. await _context.SaveChangesAsync();
  168. _logger.LogInformation($"TechnologyApplicants saved in database");
  169. }
  170. public async Task ImportApplicant(List<ApplicantImportDto> requests)
  171. {
  172. _logger.LogInformation($"Create applicant instance with sent data");
  173. var res = new List<Applicant>();
  174. var user = await _userService.GetFirst();
  175. foreach (var request in requests) {
  176. Applicant applicant = new Applicant
  177. {
  178. FirstName = request.FirstName ?? "",
  179. LastName = request.LastName ?? "",
  180. CV = request.CV ?? "",
  181. Email = request.Email ?? "",
  182. PhoneNumber = request.PhoneNumber ?? "",
  183. GithubLink = request.GithubLink ?? "",
  184. LinkedlnLink = request.LinkedlnLink ?? "",
  185. BitBucketLink = request.BitBucketLink ?? "",
  186. Position = "",
  187. DateOfApplication = request.DateOfApplication,
  188. TypeOfEmployment = request.TypeOfEmployment == "Praksa" ? TypesOfEmployment.Intership : TypesOfEmployment.Posao,
  189. Experience = request.Experience,
  190. ApplicationChannel = request.ApplicationChannel ?? "Putem sajta",
  191. // MORA DA SE UVEDE KO JE DAO KOMENTAR DA LI DA STAVIMO DA JE DANIJELA SVIMA STAVILA KOMENTARE ILI ??
  192. Comments = new List<Comment>
  193. {
  194. new Comment
  195. {
  196. User = user,
  197. Content = request.Comment
  198. }
  199. },
  200. Ads = new List<Ad> { request.Ad },
  201. SelectionProcesses = new(),
  202. TechnologyApplicants = new()
  203. };
  204. res.Add(applicant);
  205. }
  206. await _context.AddRangeAsync(res);
  207. await _context.SaveChangesAsync();
  208. _logger.LogInformation($"Saving applicant in database");
  209. _logger.LogInformation($"Applicant saved in database");
  210. }
  211. public async Task<List<ApplicantOptionsDTO>> GetOptions()
  212. {
  213. var res = await _context.Applicants.ToListAsync();
  214. return _mapper.Map<List<ApplicantOptionsDTO>>(res);
  215. }
  216. public async Task<ServiceResponseDTO<object>> InitializeProcess(ApplicantProcessRequestDTO model)
  217. {
  218. var applicant = await _context.Applicants.Include(n => n.SelectionProcesses).Where(n=> n.ApplicantId ==model.ApplicantId).FirstOrDefaultAsync();
  219. if (applicant == null)
  220. return new ServiceResponseDTO<object>
  221. {
  222. IsError = true,
  223. ErrorMessage = "Applicant does not exist."
  224. };
  225. applicant.SelectionProcesses.Add(new SelectionProcess
  226. {
  227. Name = StringGenerator.GenerateRandomPassword(),
  228. SchedulerId = model.SchedulerId,
  229. SelectionLevelId = 1,
  230. Status = model.Appointment != null ? "Zakazan" : "Čeka na zakazivanje",
  231. Date = model.Appointment
  232. });
  233. await _context.SaveChangesAsync();
  234. return new ServiceResponseDTO<object>
  235. {
  236. Data = true
  237. };
  238. }
  239. public async Task<string> GetCV(string fileName)
  240. {
  241. CloudBlockBlob blockBlob;
  242. await using (MemoryStream memoryStream = new())
  243. {
  244. string blobstorageconnection = _configuration.GetValue<string>("BlobConnectionString");
  245. CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
  246. CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
  247. CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(_configuration.GetValue<string>("BlobContainerName"));
  248. blockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
  249. await blockBlob.DownloadToStreamAsync(memoryStream);
  250. Stream blobStream = blockBlob.OpenReadAsync().Result;
  251. return ConvertToBase64(blobStream);
  252. }
  253. }
  254. private static string ConvertToBase64(Stream stream)
  255. {
  256. byte[] bytes;
  257. using (var memoryStream = new MemoryStream())
  258. {
  259. stream.CopyTo(memoryStream);
  260. bytes = memoryStream.ToArray();
  261. }
  262. string base64 = Convert.ToBase64String(bytes);
  263. return base64;
  264. }
  265. //public async Task CreateApplicant(ApplicantCreateDto applicantCreateDto)
  266. //{
  267. // var applicant = _mapper.Map<Applicant>(applicantCreateDto);
  268. // await _context.Applicants.AddAsync(applicant);
  269. // await _context.SaveChangesAsync();
  270. //}
  271. //public async Task UpdateApplicant(int id, ApplicantUpdateDto applicantUpdateDto)
  272. //{
  273. // var applicant = await _context.Applicants.FindAsync(id);
  274. // if (applicant is null)
  275. // throw new EntityNotFoundException("Applicant not found");
  276. // _mapper.Map(applicantUpdateDto, applicant);
  277. // _context.Entry(applicant).State = EntityState.Modified;
  278. // await _context.SaveChangesAsync();
  279. //}
  280. }
  281. }