using AutoMapper; using DamageAssesment.Api.SurveyResponses.Db; using DamageAssesment.Api.SurveyResponses.Interfaces; using DamageAssesment.Api.SurveyResponses.Models; using Microsoft.EntityFrameworkCore; namespace DamageAssesment.Api.SurveyResponses.Providers { public class SurveyResponsesProvider : ISurveysResponse { private readonly SurveyResponseDbContext surveyResponseDbContext; private readonly ILogger logger; private readonly IAnswerServiceProvider answerServiceProvider; private readonly IRegionServiceProvider regionServiceProvider; private readonly ILocationServiceProvider locationServiceProvider; private readonly IEmployeeServiceProvider employeeServiceProvider; private readonly IAttachmentServiceProvider attachmentServiceProvider; private readonly IQuestionServiceProvider questionServiceProvider; private readonly ISurveyServiceProvider surveyServiceProvider; private readonly IMapper mapper; public SurveyResponsesProvider(SurveyResponseDbContext surveyResponseDbContext, ILogger logger, IAnswerServiceProvider answerServiceProvider, IRegionServiceProvider regionServiceProvider, ILocationServiceProvider locationServiceProvider, IEmployeeServiceProvider employeeServiceProvider, IAttachmentServiceProvider attachmentServiceProvider, IQuestionServiceProvider questionServiceProvider, ISurveyServiceProvider surveyServiceProvider, IMapper mapper) { this.surveyResponseDbContext = surveyResponseDbContext; this.logger = logger; this.answerServiceProvider = answerServiceProvider; this.regionServiceProvider = regionServiceProvider; this.locationServiceProvider = locationServiceProvider; this.employeeServiceProvider = employeeServiceProvider; this.attachmentServiceProvider = attachmentServiceProvider; this.questionServiceProvider = questionServiceProvider; this.surveyServiceProvider = surveyServiceProvider; this.mapper = mapper; // seedData(); } private void seedData() { if (!surveyResponseDbContext.SurveyResponses.Any()) { surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 1, SurveyId = 1, EmployeeId = 1, LocationId = 1, ClientDevice = "Mobile", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 2, SurveyId = 1, EmployeeId = 2, LocationId = 2, ClientDevice = "Desktop", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 3, SurveyId = 3, EmployeeId = 4, LocationId = 1, ClientDevice = "Mobile", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 4, SurveyId = 4, EmployeeId = 1, LocationId = 2, ClientDevice = "Desktop", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "false", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 6, SurveyId = 1, EmployeeId = 4, LocationId = 2, ClientDevice = "Desktop", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "true", CreatedDate = DateTime.Now }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 7, SurveyId = 1, EmployeeId = 4, LocationId = 3, ClientDevice = "Desktop", Latitude = 98.8767, Longitute = -129.9897, KeyAnswerResult = "false", CreatedDate = DateTime.Now }); surveyResponseDbContext.SaveChanges(); } } public async Task<(bool IsSuccess, dynamic Answers, string ErrorMessage)> GetAnswersByRegionAsync(int surveyId) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); var listSurveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.SurveyId == surveyId); if (listSurveyResponse.Any()) { var answers = await getAnswersByRegionAndSurveyIdAsync(listSurveyResponse); return (true, answers, "Request Successful."); } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic SurveyResponse, string ErrorMessage)> GetSurveyResponseByIdAsync(int responseId) { try { logger?.LogInformation("Querying to get SurveyResponse object from DB"); var surveyResponse = surveyResponseDbContext.SurveyResponses.Where(s => s.Id == responseId).SingleOrDefault(); if (surveyResponse != null) { var answers = await getSurveyResponseByResponseIdAsync(surveyResponse); if (answers != null) return (true, answers, "Request Successful."); else { answers = new { }; return (true, answers, "Empty object returned"); } } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic SurveyResponses, string ErrorMessage)> GetSurveyResponsesBySurveyAsync(int surveyId) { try { logger?.LogInformation("Querying to get Survey object from microservice"); var survey = await surveyServiceProvider.getSurveyAsync(surveyId); if (survey != null) { var answers = await getSurveyResponsesBySurveyIdAsync(surveyId); if (answers != null) return (true, answers, "Request Successful."); else { answers = new List(); return (true, answers, "Empty object returned"); } } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic SurveyResponses, string ErrorMessage)> GetSurveyResponsesBySurveyAndLocationAsync(int surveyId, int locationId) { try { logger?.LogInformation("Querying to get Survey object from microservice"); var survey = await surveyServiceProvider.getSurveyAsync(surveyId); if (survey != null) { var answers = await getSurveyResponsesBySurveyIdLocationIdAsync(surveyId, locationId); if (answers != null) return (true, answers, "Request Successful."); else { answers = new List(); return (true, answers, "Empty object returned"); } } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic SurveyResponses, string ErrorMessage)> GetSurveyResponsesByMaintenanceCenterAsync(int surveyId) { try { logger?.LogInformation("Querying to get Survey object from microservice"); var survey = await surveyServiceProvider.getSurveyAsync(surveyId); if (survey != null) { var answers = await getResultsByMaintenanceCenterAsync(surveyId); if (answers != null) return (true, answers, "Request Successful."); else { answers = new List(); return (true, answers, "Empty object returned"); } } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic SurveyResponses, string ErrorMessage)> GetResponsesByAnswerAsync(int surveyId, int questionId, string answer) { try { logger?.LogInformation("Querying to get Survey object from microservice"); var survey = await surveyServiceProvider.getSurveyAsync(surveyId); var question = await questionServiceProvider.getQuestionsAsync(questionId); bool IsCorrectAnswer = answer.ToLower().Equals("yes") || answer.ToLower().Equals("no") ? true : false; if (survey != null && question != null && IsCorrectAnswer) { var answers = await getSurveyResponsesByAnswerAsync(survey, question, answer); if (answers != null) return (true, answers, "Request Successful."); else { answers = new List(); return (true, answers, "Empty object returned"); } } else { return (false, null, "Not found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, dynamic surveyResponses, string ErrorMessage)> GetSurveyResponsesAsync() { try { var answers = await getAllSurveyResponsesAsync(); if (answers != null) return (true, answers, "Request Successful."); else { answers = new List(); return (true, answers, "Empty object returned"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyResponseAsync(Models.SurveyResponse surveyResponse) { try { if (surveyResponse != null) { var _surveyResponse = mapper.Map(surveyResponse); surveyResponseDbContext.SurveyResponses.Add(_surveyResponse); await surveyResponseDbContext.SaveChangesAsync(); surveyResponse.Id = _surveyResponse.Id; return (true, surveyResponse, "Request Successful"); } else { logger?.LogInformation($"SurveyResponse cannot be added"); return (false, null, "SurveyResponse cannot be added"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PutSurveyResponseAsync(int Id, Models.SurveyResponse SurveyResponse) { try { if (SurveyResponse != null) { var _SurveyResponse = await surveyResponseDbContext.SurveyResponses.AsNoTracking().Where(s => s.Id == Id).FirstOrDefaultAsync(); if (_SurveyResponse != null) { var response = mapper.Map(SurveyResponse); surveyResponseDbContext.Update(response); await surveyResponseDbContext.SaveChangesAsync(); return (true, SurveyResponse, "Successful"); } else { logger?.LogInformation($"SurveyReponseId = {Id} Not found"); return (false, null, "Not Found"); } } else { logger?.LogInformation($"SurveyReponseId = {Id} Bad Request"); return (false, null, "Bad request"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> DeleteSurveyResponseAsync(int Id) { try { var _SurveyResponse = await surveyResponseDbContext.SurveyResponses.Where(s => s.Id == Id).FirstOrDefaultAsync(); if (_SurveyResponse != null) { surveyResponseDbContext.Remove(_SurveyResponse); await surveyResponseDbContext.SaveChangesAsync(); return (true, mapper.Map(_SurveyResponse), "Successful"); } else { logger?.LogInformation($"SurveyReponseId = {Id} Not found"); return (false, null, "Not Found"); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } //Method to get Answers by region with surveyId as input parameter private async Task getAnswersByRegionAndSurveyIdAsync(IQueryable surveyResponses) { try { var answersList = await answerServiceProvider.getAnswersAsync(); if (answersList == null || !answersList.Any()) return null; //get all the answers for the particular survey var surveyAnswers = answersList.Join( surveyResponses, answer => answer.SurveyResponseId, surveyResponse => surveyResponse.Id, (answer, surveyResponse) => new { answer.Id, answer.QuestionId, answer.AnswerText, answer.Comment, surveyResponse.LocationId, SurveyResponseId = surveyResponse.Id }); if (surveyAnswers == null || !surveyAnswers.Any()) return null; var regions = await regionServiceProvider.getRegionsAsync(); var locations = await locationServiceProvider.getLocationsAsync(); if (regions == null || !regions.Any() || locations == null || !locations.Any()) return null; //get all the answers based on the locations var result = from answer in surveyAnswers from location in locations where answer.LocationId.Equals(location.Id) select new { answer.Id, answer.QuestionId, answer.AnswerText, answer.Comment, location.RegionId, LocationId = location.Id, answer.SurveyResponseId }; //group records by answer and region var q = from e in result group e by (e.RegionId, e.AnswerText) into g select new { g.Key.RegionId, Answers = new { g.Key.AnswerText, Counter = g.Count() } }; //build the result List resultList = new List(); foreach (Region region in regions) { var answers = from u in q.ToList() where u.RegionId.Equals(region.Id) select u.Answers; resultList.Add(new { RegionId = region.Id, region.Name, region.Abbreviation, Answers = answers}); } //return the object result return new { Regions = resultList }; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResultAsync()"); return null; } } //Method to get Survey Response by ResponseId private async Task getSurveyResponseByResponseIdAsync(Db.SurveyResponse surveyResponse) { try { var employee = await employeeServiceProvider.getEmployeeAsync(surveyResponse.EmployeeId); var answers = await answerServiceProvider.GetAnswersByResponseIdAsync(surveyResponse.Id); var allQuestions = await questionServiceProvider.getQuestionsAsync(); var questions = allQuestions.Where(s => s.SurveyId == surveyResponse.SurveyId); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = new { surveyResponse.Id, surveyResponse.SurveyId, surveyResponse.LocationId, surveyResponse.EmployeeId, surveyResponse.ClientDevice, surveyResponse.KeyAnswerResult, surveyResponse.Longitute, surveyResponse.Latitude, Employee = employee, answers = from ans in answers select new { ans.QuestionId, ans.Id, ans.AnswerText, ans.Comment, Questions = (from q in questions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResultAsync()"); return null; } } //Method to get Survey Responses by surveyId private async Task getSurveyResponsesBySurveyIdAsync(int surveyId) { try { var surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId).ToListAsync(); var employees = await employeeServiceProvider.getEmployeesAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var questions = await questionServiceProvider.getQuestionsAsync(); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; //var surveyQuestions = await questionServiceProvider.getSurveyQuestionsAsync(surveyId); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResonses select new { r.Id, r.SurveyId, r.LocationId, r.EmployeeId, r.ClientDevice, r.KeyAnswerResult, r.Longitute, r.Latitude, Employee = (from e in employees where e.Id == r.EmployeeId select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id select new { ans.Id, ans.QuestionId, ans.AnswerText, ans.Comment, Questions = (from q in surveyQuestions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); return null; } } //Method to get All Survey Responses private async Task getAllSurveyResponsesAsync() { try { var surveyResonses = await surveyResponseDbContext.SurveyResponses.ToListAsync(); var employees = await employeeServiceProvider.getEmployeesAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var questions = await questionServiceProvider.getQuestionsAsync(); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResonses select new { r.Id, r.SurveyId, r.LocationId, r.EmployeeId, r.ClientDevice, r.KeyAnswerResult, r.Longitute, r.Latitude, Employee = (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id select new { ans.Id, ans.QuestionId, ans.AnswerText, ans.Comment, Questions = (from q in questions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); return null; } } //Method to get Answers By Maintenance Center by surveyId private async Task getResultsByMaintenanceCenterAsync(int surveyId) { try { var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId).ToListAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var locations = await locationServiceProvider.getLocationsAsync(); var maintenanceCenters = locations.DistinctBy(m => m.MaintenanceCenter); //get all the answers for the particular survey var surveyAnswers = from resp in surveyResponses from ans in answers where ans.SurveyResponseId.Equals(resp.Id) select new { AnswerId = ans.Id, ans.QuestionId, ans.AnswerText, ans.Comment, resp.LocationId, ResponseId = resp.Id }; //get all the answers with location var surveyAnswersLocations = from surveyAns in surveyAnswers from location in locations where surveyAns.LocationId.Equals(location.Id) select new { surveyAns, location.MaintenanceCenter }; //aggreting the answers var aggregatedResult = from e in surveyAnswersLocations group e by (e.MaintenanceCenter, e.surveyAns.AnswerText) into g select new { g.Key.MaintenanceCenter, Answers = new { g.Key.AnswerText, Counter = g.Count() } }; //format the result foreach maintenance center List results = new List(); foreach (Location m in maintenanceCenters) { var _answers = aggregatedResult.Where(x => x.MaintenanceCenter.Equals(m.MaintenanceCenter)).Select(x => x.Answers).ToList(); results.Add(new { m.Name, m.Id, m.RegionId, m.MaintenanceCenter, m.SchoolType, Answers = _answers }); } return results; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); return null; } } //Method to get Survey Responses by surveyId and LocationId private async Task getSurveyResponsesBySurveyIdLocationIdAsync(int surveyId, int locationId) { try { var surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == surveyId && x.LocationId.Equals(locationId)).ToListAsync(); var employees = await employeeServiceProvider.getEmployeesAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var questions = await questionServiceProvider.getQuestionsAsync(); var surveyQuestions = from q in questions where q.SurveyId == surveyId select q; var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResonses select new { r.Id, r.SurveyId, r.LocationId, r.EmployeeId, r.ClientDevice, r.KeyAnswerResult, r.Longitute, r.Latitude, Employee = (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id select new { ans.QuestionId, ans.Id, ans.AnswerText, ans.Comment, Questions = (from q in surveyQuestions where q.Id == ans.QuestionId select new { q.Id, q.QuestionNumber, q.CategoryId, q.Text }).SingleOrDefault(), Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); return null; } } //Method to get Survey Responses by surveyId questionId and answer private async Task getSurveyResponsesByAnswerAsync(Survey survey, Question question, string answer) { try { var surveyResponses = await surveyResponseDbContext.SurveyResponses.Where(x => x.SurveyId == survey.Id).ToListAsync(); var answers = await answerServiceProvider.getAnswersAsync(); var employees = await employeeServiceProvider.getEmployeesAsync(); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResponses select new { r.Id, r.SurveyId, r.LocationId, r.EmployeeId, r.ClientDevice, r.KeyAnswerResult, r.Longitute, r.Latitude, Employee = (from e in employees where r.EmployeeId == e.Id select new { e.Id, e.Name, e.BirthDate, e.Email, e.OfficePhoneNumber }).SingleOrDefault(), answers = from ans in answers where ans.SurveyResponseId == r.Id && ans.QuestionId == question.Id && ans.AnswerText.ToLower().Equals(answer.ToLower()) select new { ans.QuestionId, AnswerId = ans.Id, ans.AnswerText, ans.Comment, Question = question, Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result; } catch (Exception ex) { logger?.LogError($"Exception Found : {ex.Message} - Ref: SurveyResponsesProvider.getSurveyResponseBySurveyIdAsync()"); return null; } } async Task ProcessAnswers(AnswerRequest answerRequest, int surveyResponseId) { if (answerRequest != null) { var answer = await answerServiceProvider.PostAnswersAsync(new Models.Answer { QuestionId = answerRequest.QuestionId, AnswerText = answerRequest.AnswerText, Comment = answerRequest.Comment, SurveyResponseId = surveyResponseId }); if (answer != null) { List listAnswerInfo = new List(); listAnswerInfo.Add(new AnswerInfo { AnswerId = answer.Id, postedFiles = answerRequest.PostedFiles }); var attachments = attachmentServiceProvider.PostAttachmentsAsync(new AttachmentInfo { ResponseId = surveyResponseId, Answers = listAnswerInfo }); string message = $"Answer for question {answerRequest.QuestionId} saved to the database"; logger?.LogInformation(message); return (true); } else { string message = $"Answer for question {answerRequest.QuestionId} cannot be saved to the database"; logger?.LogInformation(message); return (false); } } else { var message = $"Answer for question {answerRequest.QuestionId} cannot be saved to the database - answerRequest object is null"; logger?.LogInformation(message); return (false); } } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyAnswersAsync(Models.Request request) { try { if (request != null) { var response = await PostSurveyResponseAsync(new Models.SurveyResponse { SurveyId = request.SurveyId, EmployeeId = request.EmployeeId, LocationId = request.LocationId, ClientDevice = request.ClientDevice, KeyAnswerResult = request.KeyAnswerResult, Latitude = Convert.ToDouble(request.Latitude), Longitute = Convert.ToDouble(request.Longitute), CreatedDate=DateTime.Now }); if (response.IsSuccess) { var surveyResponse = response.SurveyResponse; var tasks = request.Answers.Select(x => ProcessAnswers(x, surveyResponse.Id)); await Task.WhenAll(tasks); return (true, surveyResponse, null); } else { var message = "Survey answers cannot be saved to the database"; logger?.LogInformation(message); return (false, null, message); } } else { var message = "Request failed because null object is submitted"; logger?.LogInformation(message); return (false, null, message); } } catch (Exception ex) { logger?.LogError(ex.ToString()); return (false, null, ex.Message); } } } }