using AutoMapper; using DamageAssesment.Api.SurveyResponses.Db; using DamageAssesment.Api.SurveyResponses.Interfaces; using DamageAssesment.Api.SurveyResponses.Models; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Internal; using System.Diagnostics; using static Microsoft.EntityFrameworkCore.DbLoggerCategory; 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 = "Emp1", LocationId = "Loc1" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 2, SurveyId = 1, EmployeeId = "Emp2", LocationId = "Loc2" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 3, SurveyId = 3, EmployeeId = "Emp4", LocationId = "Loc1" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 4, SurveyId = 4, EmployeeId = "Emp1", LocationId = "Loc2" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 5, SurveyId = 1, EmployeeId = "Emp3", LocationId = "Loc3" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 6, SurveyId = 1, EmployeeId = "Emp4", LocationId = "Loc2" }); surveyResponseDbContext.SurveyResponses.Add(new Db.SurveyResponse { Id = 7, SurveyId = 1, EmployeeId = "Emp4", LocationId = "Loc3" }); 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, string 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 surveyResponses = await surveyResponseDbContext.SurveyResponses.ToListAsync(); surveyResponse.Id = surveyResponses.Count + 1; surveyResponseDbContext.SurveyResponses.Add(mapper.Map(surveyResponse)); surveyResponseDbContext.SaveChanges(); return (true, surveyResponse, "Request Successful"); } else { logger?.LogInformation($"SurveyResponseID={surveyResponse.Id} cannot be added"); return (false, null, "Survey 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.Where(s => s.Id == Id).FirstOrDefaultAsync(); if (_SurveyResponse != null) { _SurveyResponse.SurveyId = SurveyResponse.SurveyId; _SurveyResponse.EmployeeId = SurveyResponse.EmployeeId; _SurveyResponse.LocationId = SurveyResponse.LocationId; surveyResponseDbContext.SaveChanges(); return (true, mapper.Map(_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); surveyResponseDbContext.SaveChanges(); 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.Id, QuestionId = answer.QuestionId, AnswerText = answer.AnswerText, Comment = answer.Comment, LocationId = 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 == location.Id select new Answer { Id = answer.Id, QuestionId = answer.QuestionId, AnswerText = answer.AnswerText, Comment = answer.Comment, RegionId = location.RegionId, LocationId = location.Id, SurveyResponseId = 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 AggregateResult { RegionId = g.Key.RegionId, Answers = new AggregateAnswer { Answer = g.Key.AnswerText, Counter = g.Count() } }; //build the result List resultList = new List(); foreach (Region region in regions) { var answers = q.Where(x => x.RegionId.Equals(region.Id)).Select(x => x.Answers).ToList(); resultList.Add(new AnswerData { RegionId = region.Id, Name = region.Name, Abbreviation = region.Abbreviation, Answers = answers }); } //return the object result return new ResultData { 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 surveyResonses = await surveyResponseDbContext.SurveyResponses.Where(x => x.Id == surveyResponse.Id).ToListAsync(); //var surveyResponse = surveyResonses.SingleOrDefault(); 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.Id); var attachments = await attachmentServiceProvider.getAttachmentsAsync(); var result = from r in surveyResonses select new { r.Id, r.SurveyId, r.LocationId, r.EmployeeId, 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.QuestionGroup, q.Questions }).SingleOrDefault(), Attachments = from att in attachments where att.AnswerId == ans.Id select new { att.Id, att.URI } } }; return result.SingleOrDefault(); } 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, 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.QuestionGroup, q.Questions }).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, 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.QuestionGroup, q.Questions }).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 == 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 AggregateAnswer { Answer = 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, string 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, 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.QuestionGroup, q.Questions }).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 questions = await questionServiceProvider.getQuestionsAsync(); 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, 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; } } bool ProcessAnswers(QuestionRequest questionRequest, int surveyResponseId) { if (questionRequest != null) { var answer = answerServiceProvider.PostAnswersAsync(new Answer {QuestionId = questionRequest.QuestionId, AnswerText = questionRequest.AnswerText, Comment = questionRequest.Comment, SurveyResponseId = surveyResponseId }); if (answer != null) { List listAnswerInfo = new List(); listAnswerInfo.Add(new AnswerInfo { AnswerId = answer.Id, postedFiles = questionRequest.PostedFiles }); var attachments = attachmentServiceProvider.PostAttachmentsAsync(new AttachmentInfo { ResponseId = surveyResponseId, Answers = listAnswerInfo }); string message = $"Answer for question {questionRequest.QuestionId} saved to the database"; logger?.LogInformation(message); return (true); } else { string message = $"Answer for question {questionRequest.QuestionId} cannot be saved to the database"; logger?.LogInformation(message); return (false); } } else { var message = $"Answer for question {questionRequest.QuestionId} cannot be saved to the database - questionRequest object is null"; logger?.LogInformation(message); return (false); } } public async Task<(bool IsSuccess, Models.SurveyResponse SurveyResponse, string ErrorMessage)> PostSurveyAnswersAsync(Models.AnswerRequest answers) { try { if (answers != null) { var response = await PostSurveyResponseAsync(new Models.SurveyResponse { Id = 0, SurveyId = answers.SurveyId, EmployeeId = answers.EmployeeId, LocationId = answers.LocationId }); if (response.IsSuccess) { var surveyResponse = response.SurveyResponse; var answerTasks = new List(); //new List(); //var tasks = answers.Answers.Select(x => ProcessAnswers(x,surveyResponse.SurveyResponseID)); foreach (QuestionRequest ans in answers.Answers) { ProcessAnswers(ans, surveyResponse.Id); //var stopwatch = new Stopwatch(); //stopwatch.Start(); // var task = Task.Run(() => ProcessAnswers(ans, surveyResponse.Id)); //var task = await ProcessAnswers(ans, surveyResponse.Id); //answerTasks.Add(task); //stopwatch.Stop(); //answerTasks.Add(ProcessAnswers(ans, surveyResponse.Id)); } //await Task.WhenAll(answerTasks); 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); } } } }