From e399ddfd07de15a23db1f08348de3ac3b669754e Mon Sep 17 00:00:00 2001 From: itsmostafa Date: Wed, 4 Dec 2024 10:55:13 -0800 Subject: [PATCH 1/5] feature: cset-2884 refactor reportsdatabusiness --- .../{ => ReportsData}/ReportsDataBusiness.cs | 1317 +--------------- .../ReportsData/ReportsMaturityData.cs | 1322 +++++++++++++++++ 2 files changed, 1325 insertions(+), 1314 deletions(-) rename CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/{ => ReportsData}/ReportsDataBusiness.cs (51%) create mode 100644 CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsDataBusiness.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs similarity index 51% rename from CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsDataBusiness.cs rename to CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs index bd04e89d69..7ad8ab03fc 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsDataBusiness.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs @@ -4,12 +4,9 @@ // // //////////////////////////////// -using CSETWebCore.Business.Acet; -using CSETWebCore.Business.Maturity; -using CSETWebCore.Business.Maturity.Configuration; + using CSETWebCore.Business.Question; using CSETWebCore.Business.Sal; -using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; using CSETWebCore.Helpers; using CSETWebCore.Interfaces.AdminTab; @@ -18,30 +15,22 @@ using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; using CSETWebCore.Model.Diagram; -using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; using CSETWebCore.Model.Reports; -using CSETWebCore.Model.Set; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Nelibur.ObjectMapper; using Snickler.EFCore; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Runtime.Intrinsics.Arm; -using System.Text.RegularExpressions; using System.Threading.Tasks; -using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports { - public class ReportsDataBusiness : IReportsDataBusiness - { + public partial class ReportsDataBusiness : IReportsDataBusiness + { private readonly CSETContext _context; private readonly IAssessmentUtil _assessmentUtil; private int _assessmentId; @@ -84,375 +73,6 @@ public void SetReportsAssessmentId(int assessmentId) } - /// - /// Returns an unfiltered list of MatRelevantAnswers for the current assessment. - /// The optional modelId parameter is used to get a specific model's questions. If not - /// supplied, the default model's questions are retrieved. - /// - /// - public List GetQuestionsList(int? modelId = null) - { - int targetModelId = 0; - - if (modelId == null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - if (myModel == null) - { - return new List(); - } - - targetModelId = myModel.model_id; - } - else - { - targetModelId = (int)modelId; - } - - - var lang = _tokenManager.GetCurrentLanguage(); - - _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); - - // flesh out model-specific questions - if (modelId != null) - { - _context.FillEmptyMaturityQuestionsForModel(_assessmentId, (int)modelId); - } - - var query = from a in _context.ANSWER - join m in _context.MATURITY_QUESTIONS.Include(x => x.Maturity_Level) - on a.Question_Or_Requirement_Id equals m.Mat_Question_Id - where a.Assessment_Id == _assessmentId - && m.Maturity_Model_Id == targetModelId - && a.Question_Type == "Maturity" - && !this.OutOfScopeQuestions.Contains(m.Mat_Question_Id) - orderby m.Grouping_Id, m.Maturity_Level_Id, m.Mat_Question_Id ascending - select new MatRelevantAnswers() - { - ANSWER = a, - Mat = m - }; - - var responseList = query.ToList(); - var childQuestions = responseList.FindAll(x => x.Mat.Parent_Question_Id != null); - - // Set IsParentWithChildren property for all parent questions that have child questions - foreach (var matAns in responseList) - { - if (childQuestions.Exists(x => x.Mat.Parent_Question_Id == matAns.Mat.Mat_Question_Id)) - { - matAns.IsParentWithChildren = true; - } - } - - foreach (var matAns in responseList) - { - var o = _overlay.GetMaturityQuestion(matAns.Mat.Mat_Question_Id, lang); - if (o != null) - { - matAns.Mat.Question_Title = o.QuestionTitle ?? matAns.Mat.Question_Title; - matAns.Mat.Question_Text = o.QuestionText; - matAns.Mat.Supplemental_Info = o.SupplementalInfo; - } - } - - - // if a maturity level is defined, only report on questions at or below that level - int? selectedLevel = _context.ASSESSMENT_SELECTED_LEVELS.Where(x => x.Assessment_Id == _assessmentId - && x.Level_Name == Constants.Constants.MaturityLevel).Select(x => int.Parse(x.Standard_Specific_Sal_Level)).FirstOrDefault(); - - NullOutNavigationPropeties(responseList); - - // RRA should be always be defaulted to its maximum available level (3) - // since the user can't configure it - if (targetModelId == 5) - { - selectedLevel = 3; - } - - if (selectedLevel != null && selectedLevel != 0) - { - responseList = responseList.Where(x => x.Mat.Maturity_Level.Level <= selectedLevel).ToList(); - } - - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that are considered deficient for the assessment. - /// - /// - public List GetMaturityDeficiencies(int? modelId = null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - - bool ignoreParentQuestions = false; - - // default answer values that are considered 'deficient' (in case we can't find a model config profile) - List deficientAnswerValues = new List() { "N", "U" }; - - - // try to get a configuration for the actual model - var modelProperties = new ModelProfile().GetModelProperties(targetModel.Maturity_Model_Id); - if (modelProperties != null) - { - deficientAnswerValues = modelProperties.DeficientAnswers; - ignoreParentQuestions = modelProperties.IgnoreParentQuestions; - } - - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => deficientAnswerValues.Contains(x.ANSWER.Answer_Text)).ToList(); - - - // We don't consider parent questions that have children to be unanswered for certain maturity models - // (i.e. for CRR, EDM since they just house the question extras) - if (ignoreParentQuestions) - { - responseList = responseList.Where(x => !x.IsParentWithChildren).ToList(); - } - - - // If the assessment is using a submodel, only keep the submodel's subset of questions - var maturitySubmodel = _context.DETAILS_DEMOGRAPHICS.Where(x => x.Assessment_Id == _assessmentId && x.DataItemName == "MATURITY-SUBMODEL").FirstOrDefault(); - if (maturitySubmodel != null) - { - var whitelist = _context.MATURITY_SUB_MODEL_QUESTIONS.Where(x => x.Sub_Model_Name == maturitySubmodel.StringValue).Select(q => q.Mat_Question_Id).ToList(); - responseList = responseList.Where(x => whitelist.Contains(x.Mat.Mat_Question_Id)).ToList(); - } - - return responseList; - } - - - - /// - /// Returns a list of MatRelevantAnswers that contain comments. - /// - /// - public List GetCommentsList(int? modelId = null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => !string.IsNullOrWhiteSpace(x.ANSWER.Comment)).ToList(); - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that are marked for review. - /// - /// - /// - public List GetMarkedForReviewList(int? modelId = null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => x.ANSWER.Mark_For_Review ?? false).ToList(); - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that have been answered "A". - /// - /// - public List GetAlternatesList() - { - var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); - return responseList; - } - - - /// - /// Returns a list of answered maturity questions. This was built for ACET - /// but could be used by other maturity models with some work. - /// - /// - public List GetAnsweredQuestionList() - { - List controls = new List(); - - var lang = _tokenManager.GetCurrentLanguage(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id - && targetRange.Contains(q.Maturity_Level_Id)).ToList(); - - - // apply overlay - foreach (var q in questions) - { - var o = _overlay.GetMaturityQuestion(q.Mat_Question_Id, lang); - if (o != null) - { - q.Question_Title = o.QuestionTitle ?? q.Question_Title; - q.Question_Text = o.QuestionText; - q.Supplemental_Info = o.SupplementalInfo; - q.Examination_Approach = o.ExaminationApproach; - } - } - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - - // apply translation overlay - foreach (var g in allGroupings) - { - var o = _overlay.GetMaturityGrouping(g.Grouping_Id, lang); - if (o != null) - { - g.Title = o.Title; - g.Description = o.Description; - } - } - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; - - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; - - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview - }; - - - // overlay - var o = _overlay.GetMaturityQuestion(question.QuestionId, lang); - if (o != null) - { - newQuestion.QuestionText = o.QuestionText; - } - - - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - - /// /// Primarily used for ACET which uses strings to describe their levels /// @@ -463,257 +83,6 @@ private string GetLevelLabel(int maturityLevel, List levels) return levels.FirstOrDefault(x => x.Maturity_Level_Id == maturityLevel)?.Level_Name ?? ""; } - - /// - /// Returns a list of answered maturity questions. This was built for ACET ISE - /// but could be used by other maturity models with some work. - /// - /// - public List GetIseAnsweredQuestionList() - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id - && targetRange.Contains(q.Maturity_Level_Id)).ToList(); - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; - - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; - - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - - /// - /// Returns a list of answered maturity questions. This was built for ACET ISE - /// but could be used by other maturity models with some work. - /// - /// - public List GetIseAllQuestionList() - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id).ToList(); - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; - - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; - - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - - /// /// Returns a block of data generally from the INFORMATION table plus a few others. /// @@ -2074,73 +1443,6 @@ join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id } - /// - /// - /// - /// - public List GetMaturityModelData() - { - List mat_questions = new List(); - List mat_models = new List(); - - _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); - - var query = ( - from amm in _context.AVAILABLE_MATURITY_MODELS - join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id - join mq in _context.MATURITY_QUESTIONS on mm.Maturity_Model_Id equals mq.Maturity_Model_Id - join ans in _context.ANSWER on mq.Mat_Question_Id equals ans.Question_Or_Requirement_Id - join asl in _context.ASSESSMENT_SELECTED_LEVELS on amm.Assessment_Id equals asl.Assessment_Id - where amm.Assessment_Id == _assessmentId - && ans.Assessment_Id == _assessmentId - && ans.Is_Maturity == true - && asl.Level_Name == Constants.Constants.MaturityLevel - select new { amm, mm, mq, ans, asl } - ).ToList(); - var models = query.Select(x => new { x.mm, x.asl }).Distinct(); - foreach (var model in models) - { - MaturityReportData.MaturityModel newModel = new MaturityReportData.MaturityModel(); - newModel.MaturityModelName = model.mm.Model_Name; - newModel.MaturityModelID = model.mm.Maturity_Model_Id; - if (Int32.TryParse(model.asl.Standard_Specific_Sal_Level, out int lvl)) - { - newModel.TargetLevel = lvl; - } - else - { - newModel.TargetLevel = null; - } - mat_models.Add(newModel); - } - - foreach (var queryItem in query) - { - MaturityQuestion newQuestion = new MaturityQuestion(); - newQuestion.Mat_Question_Id = queryItem.mq.Mat_Question_Id; - newQuestion.Question_Title = queryItem.mq.Question_Title; - newQuestion.Question_Text = queryItem.mq.Question_Text; - newQuestion.Supplemental_Info = queryItem.mq.Supplemental_Info; - newQuestion.Examination_Approach = queryItem.mq.Examination_Approach; - newQuestion.Grouping_Id = queryItem.mq.Grouping_Id ?? 0; - newQuestion.Parent_Question_Id = queryItem.mq.Parent_Question_Id; - newQuestion.Maturity_Level = queryItem.mq.Maturity_Level_Id; - newQuestion.Set_Name = queryItem.mm.Model_Name; - newQuestion.Sequence = queryItem.mq.Sequence; - newQuestion.Maturity_Model_Id = queryItem.mm.Maturity_Model_Id; - newQuestion.Answer = queryItem.ans; - - mat_models.Where(x => x.MaturityModelID == newQuestion.Maturity_Model_Id) - .FirstOrDefault() - .MaturityQuestions.Add(newQuestion); - - mat_questions.Add(newQuestion); - } - - return mat_models; - } - - /// /// Formats first and last name. If the name is believed to be a domain\userid, /// the userid is returned with the domain removed. @@ -2244,618 +1546,5 @@ public string GetAssessmentGuid(int assessmentId) return _context.ASSESSMENTS.Where(x => x.Assessment_Id == assessmentId).Select(x => x.Assessment_GUID).FirstOrDefault().ToString(); } - public List GetCieQuestionList(int matLevel, bool filterForNa = false) - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - //var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - List questions = new List(); - - questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id).ToList(); - - // Get all MATURITY answers for the assessment - //IQueryable answers = new IQueryable(); - - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - if (filterForNa) - { - answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity" && x.Answer_Text == "NA") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - } - - Dictionary> docDictionary = new Dictionary>(); - - List documentList = new List(); - - var results = (from f in _context.DOCUMENT_FILE - join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id - join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id - join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id - where f.Assessment_Id == _assessmentId - select new { f, da, a, q }).ToList(); - - var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); - - results.ForEach(doc => - { - DocumentWithAnswerId newDoc = new DocumentWithAnswerId() - { - Answer_Id = doc.da.Answer_Id, - Title = doc.f.Title, - FileName = doc.f.Name, - Document_Id = doc.da.Document_Id, - Question_Id = doc.a.Question_Or_Requirement_Id, - Question_Title = doc.q.Question_Title - }; - documentList.Add(newDoc); - if (docDictionary.ContainsKey(newDoc.Question_Id)) - { - docDictionary[newDoc.Question_Id].Add(newDoc); - } - else - { - docDictionary.Add(newDoc.Question_Id, [newDoc]); - } - }); - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List(), - Questions = new List() - }; - - - if (assesmentFactor.Questions.Count > 0) - { - foreach (var question in assesmentFactor.Questions) - { - // if the report shows N/A only, make sure the answer's included are only "NA" - if (question.Answer != null && (filterForNa ? question.Answer == "NA" : true)) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - if (newQuestion.MaturityLevel == "5") - { - newAssesmentFactor.Questions.Add(newQuestion); - } - } - } - } - foreach (var component in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = component.Title, - IsDeficient = false, - Questions = new List(), - }; - - foreach (var question in component.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - //newAssesmentFactor.Questions.AddRange(newComponent.Questions); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - //} - - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - - public List GetCieMfrQuestionList() - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - //var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - List questions = new List(); - - questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id).ToList(); - - // Get all MATURITY answers for the assessment - //IQueryable answers = new IQueryable(); - - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - Dictionary> docDictionary = new Dictionary>(); - - List documentList = new List(); - - var results = (from f in _context.DOCUMENT_FILE - join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id - join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id - join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id - where f.Assessment_Id == _assessmentId - select new { f, da, a, q }).ToList(); - - var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); - - results.ForEach(doc => - { - DocumentWithAnswerId newDoc = new DocumentWithAnswerId() - { - Answer_Id = doc.da.Answer_Id, - Title = doc.f.Title, - FileName = doc.f.Name, - Document_Id = doc.da.Document_Id, - Question_Id = doc.a.Question_Or_Requirement_Id, - Question_Title = doc.q.Question_Title - }; - documentList.Add(newDoc); - if (docDictionary.ContainsKey(newDoc.Question_Id)) - { - docDictionary[newDoc.Question_Id].Add(newDoc); - } - else - { - docDictionary.Add(newDoc.Question_Id, [newDoc]); - } - }); - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List(), - Questions = new List() - }; - - - if (assesmentFactor.Questions.Count > 0) - { - foreach (var question in assesmentFactor.Questions) - { - // make sure only MarkForReview quest6ions are included - if (question.Answer != null && question.MarkForReview) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - if (newQuestion.MaturityLevel == "5") - { - newAssesmentFactor.Questions.Add(newQuestion); - } - } - } - } - foreach (var component in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = component.Title, - IsDeficient = false, - Questions = new List(), - }; - - foreach (var question in component.Questions) - { - if (question.Answer != null && question.MarkForReview) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - //newAssesmentFactor.Questions.AddRange(newComponent.Questions); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - //} - - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - // - - public List GetCieDocumentsForAssessment() - { - Dictionary> docDictionary = new Dictionary>(); - - List documentList = new List(); - - var results = (from f in _context.DOCUMENT_FILE - join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id - join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id - join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id - where f.Assessment_Id == _assessmentId - select new { f, da, a, q }).ToList(); - - var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); - - results.ForEach(doc => - { - DocumentWithAnswerId newDoc = new DocumentWithAnswerId() - { - Answer_Id = doc.da.Answer_Id, - Title = doc.f.Title, - FileName = doc.f.Name, - Document_Id = doc.da.Document_Id, - Question_Id = doc.a.Question_Or_Requirement_Id, - Question_Title = doc.q.Question_Title - }; - documentList.Add(newDoc); - if (docDictionary.ContainsKey(newDoc.Question_Id)) - { - docDictionary[newDoc.Question_Id].Add(newDoc); - } - else - { - docDictionary.Add(newDoc.Question_Id, [newDoc]); - } - }); - - // - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - List questions = new List(); - - questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id).ToList(); - - - // Get all MATURITY answers for the assessment - //IQueryable answers = new IQueryable(); - - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - AreQuestionsDeficient = false, - Components = new List(), - Questions = new List() - }; - - - if (assesmentFactor.Questions.Count > 0) - { - foreach (var question in assesmentFactor.Questions) - { - // if the report shows N/A only, make sure the answer's included are only "NA" - if (docDictionary.ContainsKey(question.QuestionId)) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary[question.QuestionId], - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - if (newQuestion.MaturityLevel == "5") - { - newAssesmentFactor.Questions.Add(newQuestion); - } - } - } - } - foreach (var component in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = component.Title, - IsDeficient = false, - Questions = new List(), - }; - - foreach (var question in component.Questions) - { - if (docDictionary.ContainsKey(question.QuestionId)) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = question.MaturityLevel.ToString(), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer, - Documents = docDictionary[question.QuestionId], - Visible = true - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - //newAssesmentFactor.Questions.AddRange(newComponent.Questions); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - //} - - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - // - - return maturityDomains; - } } } diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs new file mode 100644 index 0000000000..64c752dde9 --- /dev/null +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs @@ -0,0 +1,1322 @@ +//////////////////////////////// +// +// Copyright 2024 Battelle Energy Alliance, LLC +// +// +//////////////////////////////// +using CSETWebCore.Business.Maturity; +using CSETWebCore.Business.Maturity.Configuration; +using CSETWebCore.DataLayer.Model; +using CSETWebCore.Interfaces.Reports; +using CSETWebCore.Model.Document; +using CSETWebCore.Model.Maturity; +using CSETWebCore.Model.Question; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; + + +namespace CSETWebCore.Business.Reports +{ + public partial class ReportsDataBusiness : IReportsDataBusiness + { + /// + /// Returns an unfiltered list of MatRelevantAnswers for the current assessment. + /// The optional modelId parameter is used to get a specific model's questions. If not + /// supplied, the default model's questions are retrieved. + /// + /// + public List GetQuestionsList(int? modelId = null) + { + int targetModelId = 0; + + if (modelId == null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + if (myModel == null) + { + return new List(); + } + + targetModelId = myModel.model_id; + } + else + { + targetModelId = (int)modelId; + } + + + var lang = _tokenManager.GetCurrentLanguage(); + + _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); + + // flesh out model-specific questions + if (modelId != null) + { + _context.FillEmptyMaturityQuestionsForModel(_assessmentId, (int)modelId); + } + + var query = from a in _context.ANSWER + join m in _context.MATURITY_QUESTIONS.Include(x => x.Maturity_Level) + on a.Question_Or_Requirement_Id equals m.Mat_Question_Id + where a.Assessment_Id == _assessmentId + && m.Maturity_Model_Id == targetModelId + && a.Question_Type == "Maturity" + && !this.OutOfScopeQuestions.Contains(m.Mat_Question_Id) + orderby m.Grouping_Id, m.Maturity_Level_Id, m.Mat_Question_Id ascending + select new MatRelevantAnswers() + { + ANSWER = a, + Mat = m + }; + + var responseList = query.ToList(); + var childQuestions = responseList.FindAll(x => x.Mat.Parent_Question_Id != null); + + // Set IsParentWithChildren property for all parent questions that have child questions + foreach (var matAns in responseList) + { + if (childQuestions.Exists(x => x.Mat.Parent_Question_Id == matAns.Mat.Mat_Question_Id)) + { + matAns.IsParentWithChildren = true; + } + } + + foreach (var matAns in responseList) + { + var o = _overlay.GetMaturityQuestion(matAns.Mat.Mat_Question_Id, lang); + if (o != null) + { + matAns.Mat.Question_Title = o.QuestionTitle ?? matAns.Mat.Question_Title; + matAns.Mat.Question_Text = o.QuestionText; + matAns.Mat.Supplemental_Info = o.SupplementalInfo; + } + } + + + // if a maturity level is defined, only report on questions at or below that level + int? selectedLevel = _context.ASSESSMENT_SELECTED_LEVELS.Where(x => x.Assessment_Id == _assessmentId + && x.Level_Name == Constants.Constants.MaturityLevel).Select(x => int.Parse(x.Standard_Specific_Sal_Level)).FirstOrDefault(); + + NullOutNavigationPropeties(responseList); + + // RRA should be always be defaulted to its maximum available level (3) + // since the user can't configure it + if (targetModelId == 5) + { + selectedLevel = 3; + } + + if (selectedLevel != null && selectedLevel != 0) + { + responseList = responseList.Where(x => x.Mat.Maturity_Level.Level <= selectedLevel).ToList(); + } + + + return responseList; + } + + + /// + /// Returns a list of MatRelevantAnswers that are considered deficient for the assessment. + /// + /// + public List GetMaturityDeficiencies(int? modelId = null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var targetModel = myModel.model; + + + // if a model was explicitly requested, do that one + if (modelId != null) + { + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); + } + + + bool ignoreParentQuestions = false; + + // default answer values that are considered 'deficient' (in case we can't find a model config profile) + List deficientAnswerValues = new List() { "N", "U" }; + + + // try to get a configuration for the actual model + var modelProperties = new ModelProfile().GetModelProperties(targetModel.Maturity_Model_Id); + if (modelProperties != null) + { + deficientAnswerValues = modelProperties.DeficientAnswers; + ignoreParentQuestions = modelProperties.IgnoreParentQuestions; + } + + + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => deficientAnswerValues.Contains(x.ANSWER.Answer_Text)).ToList(); + + + // We don't consider parent questions that have children to be unanswered for certain maturity models + // (i.e. for CRR, EDM since they just house the question extras) + if (ignoreParentQuestions) + { + responseList = responseList.Where(x => !x.IsParentWithChildren).ToList(); + } + + + // If the assessment is using a submodel, only keep the submodel's subset of questions + var maturitySubmodel = _context.DETAILS_DEMOGRAPHICS.Where(x => x.Assessment_Id == _assessmentId && x.DataItemName == "MATURITY-SUBMODEL").FirstOrDefault(); + if (maturitySubmodel != null) + { + var whitelist = _context.MATURITY_SUB_MODEL_QUESTIONS.Where(x => x.Sub_Model_Name == maturitySubmodel.StringValue).Select(q => q.Mat_Question_Id).ToList(); + responseList = responseList.Where(x => whitelist.Contains(x.Mat.Mat_Question_Id)).ToList(); + } + + return responseList; + } + + + + /// + /// Returns a list of MatRelevantAnswers that contain comments. + /// + /// + public List GetCommentsList(int? modelId = null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var targetModel = myModel.model; + + // if a model was explicitly requested, do that one + if (modelId != null) + { + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); + } + + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => !string.IsNullOrWhiteSpace(x.ANSWER.Comment)).ToList(); + + return responseList; + } + + + /// + /// Returns a list of MatRelevantAnswers that are marked for review. + /// + /// + /// + public List GetMarkedForReviewList(int? modelId = null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var targetModel = myModel.model; + + // if a model was explicitly requested, do that one + if (modelId != null) + { + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); + } + + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => x.ANSWER.Mark_For_Review ?? false).ToList(); + + return responseList; + } + + + /// + /// Returns a list of MatRelevantAnswers that have been answered "A". + /// + /// + public List GetAlternatesList() + { + var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); + return responseList; + } + + + /// + /// Returns a list of answered maturity questions. This was built for ACET + /// but could be used by other maturity models with some work. + /// + /// + public List GetAnsweredQuestionList() + { + List controls = new List(); + + var lang = _tokenManager.GetCurrentLanguage(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id + && targetRange.Contains(q.Maturity_Level_Id)).ToList(); + + + // apply overlay + foreach (var q in questions) + { + var o = _overlay.GetMaturityQuestion(q.Mat_Question_Id, lang); + if (o != null) + { + q.Question_Title = o.QuestionTitle ?? q.Question_Title; + q.Question_Text = o.QuestionText; + q.Supplemental_Info = o.SupplementalInfo; + q.Examination_Approach = o.ExaminationApproach; + } + } + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + + // apply translation overlay + foreach (var g in allGroupings) + { + var o = _overlay.GetMaturityGrouping(g.Grouping_Id, lang); + if (o != null) + { + g.Title = o.Title; + g.Description = o.Description; + } + } + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview + }; + + + // overlay + var o = _overlay.GetMaturityQuestion(question.QuestionId, lang); + if (o != null) + { + newQuestion.QuestionText = o.QuestionText; + } + + + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + + /// + /// Returns a list of answered maturity questions. This was built for ACET ISE + /// but could be used by other maturity models with some work. + /// + /// + public List GetIseAnsweredQuestionList() + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id + && targetRange.Contains(q.Maturity_Level_Id)).ToList(); + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + /// + /// Returns a list of answered maturity questions. This was built for ACET ISE + /// but could be used by other maturity models with some work. + /// + /// + public List GetIseAllQuestionList() + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id).ToList(); + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + + /// + /// + /// + /// + public List GetMaturityModelData() + { + List mat_questions = new List(); + List mat_models = new List(); + + _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); + + var query = ( + from amm in _context.AVAILABLE_MATURITY_MODELS + join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id + join mq in _context.MATURITY_QUESTIONS on mm.Maturity_Model_Id equals mq.Maturity_Model_Id + join ans in _context.ANSWER on mq.Mat_Question_Id equals ans.Question_Or_Requirement_Id + join asl in _context.ASSESSMENT_SELECTED_LEVELS on amm.Assessment_Id equals asl.Assessment_Id + where amm.Assessment_Id == _assessmentId + && ans.Assessment_Id == _assessmentId + && ans.Is_Maturity == true + && asl.Level_Name == Constants.Constants.MaturityLevel + select new { amm, mm, mq, ans, asl } + ).ToList(); + var models = query.Select(x => new { x.mm, x.asl }).Distinct(); + foreach (var model in models) + { + MaturityReportData.MaturityModel newModel = new MaturityReportData.MaturityModel(); + newModel.MaturityModelName = model.mm.Model_Name; + newModel.MaturityModelID = model.mm.Maturity_Model_Id; + if (Int32.TryParse(model.asl.Standard_Specific_Sal_Level, out int lvl)) + { + newModel.TargetLevel = lvl; + } + else + { + newModel.TargetLevel = null; + } + mat_models.Add(newModel); + } + + foreach (var queryItem in query) + { + MaturityQuestion newQuestion = new MaturityQuestion(); + newQuestion.Mat_Question_Id = queryItem.mq.Mat_Question_Id; + newQuestion.Question_Title = queryItem.mq.Question_Title; + newQuestion.Question_Text = queryItem.mq.Question_Text; + newQuestion.Supplemental_Info = queryItem.mq.Supplemental_Info; + newQuestion.Examination_Approach = queryItem.mq.Examination_Approach; + newQuestion.Grouping_Id = queryItem.mq.Grouping_Id ?? 0; + newQuestion.Parent_Question_Id = queryItem.mq.Parent_Question_Id; + newQuestion.Maturity_Level = queryItem.mq.Maturity_Level_Id; + newQuestion.Set_Name = queryItem.mm.Model_Name; + newQuestion.Sequence = queryItem.mq.Sequence; + newQuestion.Maturity_Model_Id = queryItem.mm.Maturity_Model_Id; + newQuestion.Answer = queryItem.ans; + + mat_models.Where(x => x.MaturityModelID == newQuestion.Maturity_Model_Id) + .FirstOrDefault() + .MaturityQuestions.Add(newQuestion); + + mat_questions.Add(newQuestion); + } + + return mat_models; + } + public List GetCieQuestionList(int matLevel, bool filterForNa = false) + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + //var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + List questions = new List(); + + questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id).ToList(); + + // Get all MATURITY answers for the assessment + //IQueryable answers = new IQueryable(); + + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + if (filterForNa) + { + answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity" && x.Answer_Text == "NA") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + } + + Dictionary> docDictionary = new Dictionary>(); + + List documentList = new List(); + + var results = (from f in _context.DOCUMENT_FILE + join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id + join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id + join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id + where f.Assessment_Id == _assessmentId + select new { f, da, a, q }).ToList(); + + var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); + + results.ForEach(doc => + { + DocumentWithAnswerId newDoc = new DocumentWithAnswerId() + { + Answer_Id = doc.da.Answer_Id, + Title = doc.f.Title, + FileName = doc.f.Name, + Document_Id = doc.da.Document_Id, + Question_Id = doc.a.Question_Or_Requirement_Id, + Question_Title = doc.q.Question_Title + }; + documentList.Add(newDoc); + if (docDictionary.ContainsKey(newDoc.Question_Id)) + { + docDictionary[newDoc.Question_Id].Add(newDoc); + } + else + { + docDictionary.Add(newDoc.Question_Id, [newDoc]); + } + }); + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List(), + Questions = new List() + }; + + + if (assesmentFactor.Questions.Count > 0) + { + foreach (var question in assesmentFactor.Questions) + { + // if the report shows N/A only, make sure the answer's included are only "NA" + if (question.Answer != null && (filterForNa ? question.Answer == "NA" : true)) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + if (newQuestion.MaturityLevel == "5") + { + newAssesmentFactor.Questions.Add(newQuestion); + } + } + } + } + foreach (var component in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = component.Title, + IsDeficient = false, + Questions = new List(), + }; + + foreach (var question in component.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + //newAssesmentFactor.Questions.AddRange(newComponent.Questions); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + //} + + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + public List GetCieMfrQuestionList() + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + //var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + List questions = new List(); + + questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id).ToList(); + + // Get all MATURITY answers for the assessment + //IQueryable answers = new IQueryable(); + + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + Dictionary> docDictionary = new Dictionary>(); + + List documentList = new List(); + + var results = (from f in _context.DOCUMENT_FILE + join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id + join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id + join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id + where f.Assessment_Id == _assessmentId + select new { f, da, a, q }).ToList(); + + var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); + + results.ForEach(doc => + { + DocumentWithAnswerId newDoc = new DocumentWithAnswerId() + { + Answer_Id = doc.da.Answer_Id, + Title = doc.f.Title, + FileName = doc.f.Name, + Document_Id = doc.da.Document_Id, + Question_Id = doc.a.Question_Or_Requirement_Id, + Question_Title = doc.q.Question_Title + }; + documentList.Add(newDoc); + if (docDictionary.ContainsKey(newDoc.Question_Id)) + { + docDictionary[newDoc.Question_Id].Add(newDoc); + } + else + { + docDictionary.Add(newDoc.Question_Id, [newDoc]); + } + }); + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List(), + Questions = new List() + }; + + + if (assesmentFactor.Questions.Count > 0) + { + foreach (var question in assesmentFactor.Questions) + { + // make sure only MarkForReview quest6ions are included + if (question.Answer != null && question.MarkForReview) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + if (newQuestion.MaturityLevel == "5") + { + newAssesmentFactor.Questions.Add(newQuestion); + } + } + } + } + foreach (var component in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = component.Title, + IsDeficient = false, + Questions = new List(), + }; + + foreach (var question in component.Questions) + { + if (question.Answer != null && question.MarkForReview) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary.ContainsKey(question.QuestionId) ? docDictionary[question.QuestionId] : null, + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + //newAssesmentFactor.Questions.AddRange(newComponent.Questions); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + //} + + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + // + + public List GetCieDocumentsForAssessment() + { + Dictionary> docDictionary = new Dictionary>(); + + List documentList = new List(); + + var results = (from f in _context.DOCUMENT_FILE + join da in _context.DOCUMENT_ANSWERS on f.Document_Id equals da.Document_Id + join a in _context.ANSWER on da.Answer_Id equals a.Answer_Id + join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id + where f.Assessment_Id == _assessmentId + select new { f, da, a, q }).ToList(); + + var questionIds = results.DistinctBy(x => x.q.Mat_Question_Id).ToList(); + + results.ForEach(doc => + { + DocumentWithAnswerId newDoc = new DocumentWithAnswerId() + { + Answer_Id = doc.da.Answer_Id, + Title = doc.f.Title, + FileName = doc.f.Name, + Document_Id = doc.da.Document_Id, + Question_Id = doc.a.Question_Or_Requirement_Id, + Question_Title = doc.q.Question_Title + }; + documentList.Add(newDoc); + if (docDictionary.ContainsKey(newDoc.Question_Id)) + { + docDictionary[newDoc.Question_Id].Add(newDoc); + } + else + { + docDictionary.Add(newDoc.Question_Id, [newDoc]); + } + }); + + // + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + List questions = new List(); + + questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id).ToList(); + + + // Get all MATURITY answers for the assessment + //IQueryable answers = new IQueryable(); + + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + AreQuestionsDeficient = false, + Components = new List(), + Questions = new List() + }; + + + if (assesmentFactor.Questions.Count > 0) + { + foreach (var question in assesmentFactor.Questions) + { + // if the report shows N/A only, make sure the answer's included are only "NA" + if (docDictionary.ContainsKey(question.QuestionId)) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary[question.QuestionId], + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + if (newQuestion.MaturityLevel == "5") + { + newAssesmentFactor.Questions.Add(newQuestion); + } + } + } + } + foreach (var component in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = component.Title, + IsDeficient = false, + Questions = new List(), + }; + + foreach (var question in component.Questions) + { + if (docDictionary.ContainsKey(question.QuestionId)) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = question.MaturityLevel.ToString(), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer, + Documents = docDictionary[question.QuestionId], + Visible = true + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + //newAssesmentFactor.Questions.AddRange(newComponent.Questions); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + //} + + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + // + + return maturityDomains; + } + } +} From b61626e9aee1bb24a2f849a71ae230616debff99 Mon Sep 17 00:00:00 2001 From: Mostafa Abdo Date: Wed, 4 Dec 2024 16:30:51 -0800 Subject: [PATCH 2/5] split reports data logic by skin type --- ...portsMaturityData.cs => CieReportsData.cs} | 714 ++---------------- .../Reports/ReportsData/NCUAReportsData.cs | 574 ++++++++++++++ .../ReportsData/ReportsDataBusiness.cs | 403 ++++++---- 3 files changed, 886 insertions(+), 805 deletions(-) rename CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/{ReportsMaturityData.cs => CieReportsData.cs} (50%) create mode 100644 CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs similarity index 50% rename from CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs rename to CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs index 64c752dde9..424079b21b 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsMaturityData.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs @@ -4,707 +4,87 @@ // // //////////////////////////////// +using CSETWebCore.Business.Acet; using CSETWebCore.Business.Maturity; using CSETWebCore.Business.Maturity.Configuration; +using CSETWebCore.Business.Question; +using CSETWebCore.Business.Sal; +using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; +using CSETWebCore.Helpers; +using CSETWebCore.Interfaces.AdminTab; +using CSETWebCore.Interfaces.Helpers; +using CSETWebCore.Interfaces.Maturity; +using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; +using CSETWebCore.Model.Diagram; using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; +using CSETWebCore.Model.Reports; +using CSETWebCore.Model.Set; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using Nelibur.ObjectMapper; +using Snickler.EFCore; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Runtime.Intrinsics.Arm; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports { public partial class ReportsDataBusiness : IReportsDataBusiness { - /// - /// Returns an unfiltered list of MatRelevantAnswers for the current assessment. - /// The optional modelId parameter is used to get a specific model's questions. If not - /// supplied, the default model's questions are retrieved. - /// - /// - public List GetQuestionsList(int? modelId = null) - { - int targetModelId = 0; - - if (modelId == null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - if (myModel == null) - { - return new List(); - } - - targetModelId = myModel.model_id; - } - else - { - targetModelId = (int)modelId; - } - - - var lang = _tokenManager.GetCurrentLanguage(); - - _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); - - // flesh out model-specific questions - if (modelId != null) - { - _context.FillEmptyMaturityQuestionsForModel(_assessmentId, (int)modelId); - } - - var query = from a in _context.ANSWER - join m in _context.MATURITY_QUESTIONS.Include(x => x.Maturity_Level) - on a.Question_Or_Requirement_Id equals m.Mat_Question_Id - where a.Assessment_Id == _assessmentId - && m.Maturity_Model_Id == targetModelId - && a.Question_Type == "Maturity" - && !this.OutOfScopeQuestions.Contains(m.Mat_Question_Id) - orderby m.Grouping_Id, m.Maturity_Level_Id, m.Mat_Question_Id ascending - select new MatRelevantAnswers() - { - ANSWER = a, - Mat = m - }; - - var responseList = query.ToList(); - var childQuestions = responseList.FindAll(x => x.Mat.Parent_Question_Id != null); - - // Set IsParentWithChildren property for all parent questions that have child questions - foreach (var matAns in responseList) - { - if (childQuestions.Exists(x => x.Mat.Parent_Question_Id == matAns.Mat.Mat_Question_Id)) - { - matAns.IsParentWithChildren = true; - } - } - - foreach (var matAns in responseList) - { - var o = _overlay.GetMaturityQuestion(matAns.Mat.Mat_Question_Id, lang); - if (o != null) - { - matAns.Mat.Question_Title = o.QuestionTitle ?? matAns.Mat.Question_Title; - matAns.Mat.Question_Text = o.QuestionText; - matAns.Mat.Supplemental_Info = o.SupplementalInfo; - } - } - - - // if a maturity level is defined, only report on questions at or below that level - int? selectedLevel = _context.ASSESSMENT_SELECTED_LEVELS.Where(x => x.Assessment_Id == _assessmentId - && x.Level_Name == Constants.Constants.MaturityLevel).Select(x => int.Parse(x.Standard_Specific_Sal_Level)).FirstOrDefault(); - - NullOutNavigationPropeties(responseList); - - // RRA should be always be defaulted to its maximum available level (3) - // since the user can't configure it - if (targetModelId == 5) - { - selectedLevel = 3; - } - - if (selectedLevel != null && selectedLevel != 0) - { - responseList = responseList.Where(x => x.Mat.Maturity_Level.Level <= selectedLevel).ToList(); - } - - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that are considered deficient for the assessment. - /// - /// - public List GetMaturityDeficiencies(int? modelId = null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - - bool ignoreParentQuestions = false; - - // default answer values that are considered 'deficient' (in case we can't find a model config profile) - List deficientAnswerValues = new List() { "N", "U" }; - - - // try to get a configuration for the actual model - var modelProperties = new ModelProfile().GetModelProperties(targetModel.Maturity_Model_Id); - if (modelProperties != null) - { - deficientAnswerValues = modelProperties.DeficientAnswers; - ignoreParentQuestions = modelProperties.IgnoreParentQuestions; - } - - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => deficientAnswerValues.Contains(x.ANSWER.Answer_Text)).ToList(); - - - // We don't consider parent questions that have children to be unanswered for certain maturity models - // (i.e. for CRR, EDM since they just house the question extras) - if (ignoreParentQuestions) - { - responseList = responseList.Where(x => !x.IsParentWithChildren).ToList(); - } - - - // If the assessment is using a submodel, only keep the submodel's subset of questions - var maturitySubmodel = _context.DETAILS_DEMOGRAPHICS.Where(x => x.Assessment_Id == _assessmentId && x.DataItemName == "MATURITY-SUBMODEL").FirstOrDefault(); - if (maturitySubmodel != null) - { - var whitelist = _context.MATURITY_SUB_MODEL_QUESTIONS.Where(x => x.Sub_Model_Name == maturitySubmodel.StringValue).Select(q => q.Mat_Question_Id).ToList(); - responseList = responseList.Where(x => whitelist.Contains(x.Mat.Mat_Question_Id)).ToList(); - } - - return responseList; - } - - /// - /// Returns a list of MatRelevantAnswers that contain comments. + /// Formats the Title for CIE observations the way they want /// /// - public List GetCommentsList(int? modelId = null) + private void GetQuestionTitleAndTextForCie(dynamic f, + List stdList, List compList, + int answerId, + out string identifier, out string questionText) { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => !string.IsNullOrWhiteSpace(x.ANSWER.Comment)).ToList(); - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that are marked for review. - /// - /// - /// - public List GetMarkedForReviewList(int? modelId = null) - { - var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var targetModel = myModel.model; - - // if a model was explicitly requested, do that one - if (modelId != null) - { - targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); - } - - var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => x.ANSWER.Mark_For_Review ?? false).ToList(); - - return responseList; - } - - - /// - /// Returns a list of MatRelevantAnswers that have been answered "A". - /// - /// - public List GetAlternatesList() - { - var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); - return responseList; - } - - - /// - /// Returns a list of answered maturity questions. This was built for ACET - /// but could be used by other maturity models with some work. - /// - /// - public List GetAnsweredQuestionList() - { - List controls = new List(); - + identifier = ""; + questionText = ""; var lang = _tokenManager.GetCurrentLanguage(); + identifier = f.mq.Question_Title; + questionText = f.mq.Question_Text; + int groupId = f.mq.Grouping_Id ?? 0; - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id - && targetRange.Contains(q.Maturity_Level_Id)).ToList(); - - - // apply overlay - foreach (var q in questions) - { - var o = _overlay.GetMaturityQuestion(q.Mat_Question_Id, lang); - if (o != null) - { - q.Question_Title = o.QuestionTitle ?? q.Question_Title; - q.Question_Text = o.QuestionText; - q.Supplemental_Info = o.SupplementalInfo; - q.Examination_Approach = o.ExaminationApproach; - } - } - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - - // apply translation overlay - foreach (var g in allGroupings) - { - var o = _overlay.GetMaturityGrouping(g.Grouping_Id, lang); - if (o != null) - { - g.Title = o.Title; - g.Description = o.Description; - } - } - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - foreach (var domain in questionGrouping.SubGroupings) - { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; - - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; - - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview - }; - - - // overlay - var o = _overlay.GetMaturityQuestion(question.QuestionId, lang); - if (o != null) - { - newQuestion.QuestionText = o.QuestionText; - } - - - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } - } - - return maturityDomains; - } - - - /// - /// Returns a list of answered maturity questions. This was built for ACET ISE - /// but could be used by other maturity models with some work. - /// - /// - public List GetIseAnsweredQuestionList() - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id - && targetRange.Contains(q.Maturity_Level_Id)).ToList(); - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - + var groupRow = _context.MATURITY_GROUPINGS.Where(x => x.Grouping_Id == groupId).FirstOrDefault(); + int principleNumber = 0; + int phaseNumber = 0; - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) + if (groupRow.Group_Level == 2) { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; - - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; - - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } + // tracking the principle number + principleNumber = groupRow.Sequence; + identifier = "Principle " + principleNumber + " - " + identifier; } - - return maturityDomains; - } - - /// - /// Returns a list of answered maturity questions. This was built for ACET ISE - /// but could be used by other maturity models with some work. - /// - /// - public List GetIseAllQuestionList() - { - List controls = new List(); - - - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - // get the target maturity level IDs - var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); - - var questions = _context.MATURITY_QUESTIONS.Where(q => - myModel.model_id == q.Maturity_Model_Id).ToList(); - - - // Get all MATURITY answers for the assessment - var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") - from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() - select new FullAnswer() { a = a, b = b }; - - - // Get all subgroupings for this maturity model - var allGroupings = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); - - //Get All the Observations and issues with the Observations. - - - // Recursively build the grouping/question hierarchy - var questionGrouping = new MaturityGrouping(); - BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); - - var maturityDomains = new List(); - - // ToDo: Refactor the following stucture of loops - foreach (var domain in questionGrouping.SubGroupings) + else if (groupRow.Group_Level == 3) { - var newDomain = new MatAnsweredQuestionDomain() - { - Title = domain.Title, - IsDeficient = false, - AssessmentFactors = new List() - }; - foreach (var assesmentFactor in domain.SubGroupings) - { - var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() - { - Title = assesmentFactor.Title, - IsDeficient = false, - Components = new List() - }; + // tracking the phase number + // the -1 is because the "General" grouping is first at Sequence = 1, but it's hidden from the user for now (request from the client) + phaseNumber = groupRow.Sequence - 1; - foreach (var componenet in assesmentFactor.SubGroupings) - { - var newComponent = new MaturityAnsweredQuestionsComponent() - { - Title = componenet.Title, - IsDeficient = false, - Questions = new List() - }; + // finding the principle number + groupRow = _context.MATURITY_GROUPINGS.Where(x => x.Grouping_Id == groupRow.Parent_Id).FirstOrDefault(); + principleNumber = groupRow.Sequence; - foreach (var question in componenet.Questions) - { - if (question.Answer != null) - { - var newQuestion = new MaturityAnsweredQuestions() - { - Title = question.DisplayNumber, - QuestionText = question.QuestionText, - MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), - AnswerText = question.Answer, - Comment = question.Comment, - MarkForReview = question.MarkForReview, - MatQuestionId = question.QuestionId, - FreeResponseText = question.FreeResponseAnswer - }; - - if (question.Answer == "N") - { - newDomain.IsDeficient = true; - newAssesmentFactor.IsDeficient = true; - newComponent.IsDeficient = true; - } - - if (question.Comment != null) - { - newQuestion.Comments = "Yes"; - } - else - { - newQuestion.Comments = "No"; - } - - newComponent.Questions.Add(newQuestion); - } - } - if (newComponent.Questions.Count > 0) - { - newAssesmentFactor.Components.Add(newComponent); - } - } - if (newAssesmentFactor.Components.Count > 0) - { - newDomain.AssessmentFactors.Add(newAssesmentFactor); - } - } - if (newDomain.AssessmentFactors.Count > 0) - { - maturityDomains.Add(newDomain); - } + identifier = "Principle " + principleNumber + " - Phase " + phaseNumber + " - " + identifier; } - - return maturityDomains; } - /// - /// - /// - /// - public List GetMaturityModelData() - { - List mat_questions = new List(); - List mat_models = new List(); - - _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); - - var query = ( - from amm in _context.AVAILABLE_MATURITY_MODELS - join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id - join mq in _context.MATURITY_QUESTIONS on mm.Maturity_Model_Id equals mq.Maturity_Model_Id - join ans in _context.ANSWER on mq.Mat_Question_Id equals ans.Question_Or_Requirement_Id - join asl in _context.ASSESSMENT_SELECTED_LEVELS on amm.Assessment_Id equals asl.Assessment_Id - where amm.Assessment_Id == _assessmentId - && ans.Assessment_Id == _assessmentId - && ans.Is_Maturity == true - && asl.Level_Name == Constants.Constants.MaturityLevel - select new { amm, mm, mq, ans, asl } - ).ToList(); - var models = query.Select(x => new { x.mm, x.asl }).Distinct(); - foreach (var model in models) - { - MaturityReportData.MaturityModel newModel = new MaturityReportData.MaturityModel(); - newModel.MaturityModelName = model.mm.Model_Name; - newModel.MaturityModelID = model.mm.Maturity_Model_Id; - if (Int32.TryParse(model.asl.Standard_Specific_Sal_Level, out int lvl)) - { - newModel.TargetLevel = lvl; - } - else - { - newModel.TargetLevel = null; - } - mat_models.Add(newModel); - } - - foreach (var queryItem in query) - { - MaturityQuestion newQuestion = new MaturityQuestion(); - newQuestion.Mat_Question_Id = queryItem.mq.Mat_Question_Id; - newQuestion.Question_Title = queryItem.mq.Question_Title; - newQuestion.Question_Text = queryItem.mq.Question_Text; - newQuestion.Supplemental_Info = queryItem.mq.Supplemental_Info; - newQuestion.Examination_Approach = queryItem.mq.Examination_Approach; - newQuestion.Grouping_Id = queryItem.mq.Grouping_Id ?? 0; - newQuestion.Parent_Question_Id = queryItem.mq.Parent_Question_Id; - newQuestion.Maturity_Level = queryItem.mq.Maturity_Level_Id; - newQuestion.Set_Name = queryItem.mm.Model_Name; - newQuestion.Sequence = queryItem.mq.Sequence; - newQuestion.Maturity_Model_Id = queryItem.mm.Maturity_Model_Id; - newQuestion.Answer = queryItem.ans; - - mat_models.Where(x => x.MaturityModelID == newQuestion.Maturity_Model_Id) - .FirstOrDefault() - .MaturityQuestions.Add(newQuestion); - - mat_questions.Add(newQuestion); - } - - return mat_models; - } public List GetCieQuestionList(int matLevel, bool filterForNa = false) { List controls = new List(); @@ -1319,4 +699,4 @@ from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id). return maturityDomains; } } -} +} \ No newline at end of file diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs new file mode 100644 index 0000000000..cb1ac70144 --- /dev/null +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs @@ -0,0 +1,574 @@ +//////////////////////////////// +// +// Copyright 2024 Battelle Energy Alliance, LLC +// +// +//////////////////////////////// +using CSETWebCore.Business.Acet; +using CSETWebCore.Business.Maturity; +using CSETWebCore.Business.Maturity.Configuration; +using CSETWebCore.Business.Question; +using CSETWebCore.Business.Sal; +using CSETWebCore.DataLayer.Manual; +using CSETWebCore.DataLayer.Model; +using CSETWebCore.Helpers; +using CSETWebCore.Interfaces.AdminTab; +using CSETWebCore.Interfaces.Helpers; +using CSETWebCore.Interfaces.Maturity; +using CSETWebCore.Interfaces.Question; +using CSETWebCore.Interfaces.Reports; +using CSETWebCore.Model.Diagram; +using CSETWebCore.Model.Document; +using CSETWebCore.Model.Maturity; +using CSETWebCore.Model.Question; +using CSETWebCore.Model.Reports; +using CSETWebCore.Model.Set; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Nelibur.ObjectMapper; +using Snickler.EFCore; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.Intrinsics.Arm; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static Lucene.Net.Util.Fst.Util; + + +namespace CSETWebCore.Business.Reports +{ + public partial class ReportsDataBusiness : IReportsDataBusiness + { + + /// + /// Returns a list of answered maturity questions. This was built for ACET + /// but could be used by other maturity models with some work. + /// + /// + public List GetAnsweredQuestionList() + { + List controls = new List(); + + var lang = _tokenManager.GetCurrentLanguage(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id + && targetRange.Contains(q.Maturity_Level_Id)).ToList(); + + + // apply overlay + foreach (var q in questions) + { + var o = _overlay.GetMaturityQuestion(q.Mat_Question_Id, lang); + if (o != null) + { + q.Question_Title = o.QuestionTitle ?? q.Question_Title; + q.Question_Text = o.QuestionText; + q.Supplemental_Info = o.SupplementalInfo; + q.Examination_Approach = o.ExaminationApproach; + } + } + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + + // apply translation overlay + foreach (var g in allGroupings) + { + var o = _overlay.GetMaturityGrouping(g.Grouping_Id, lang); + if (o != null) + { + g.Title = o.Title; + g.Description = o.Description; + } + } + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview + }; + + + // overlay + var o = _overlay.GetMaturityQuestion(question.QuestionId, lang); + if (o != null) + { + newQuestion.QuestionText = o.QuestionText; + } + + + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + + /// + /// Primarily used for ACET which uses strings to describe their levels + /// + /// + /// + private string GetLevelLabel(int maturityLevel, List levels) + { + return levels.FirstOrDefault(x => x.Maturity_Level_Id == maturityLevel)?.Level_Name ?? ""; + } + + + /// + /// Returns a list of answered maturity questions. This was built for ACET ISE + /// but could be used by other maturity models with some work. + /// + /// + public List GetIseAnsweredQuestionList() + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id + && targetRange.Contains(q.Maturity_Level_Id)).ToList(); + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + /// + /// Returns a list of answered maturity questions. This was built for ACET ISE + /// but could be used by other maturity models with some work. + /// + /// + public List GetIseAllQuestionList() + { + List controls = new List(); + + + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var myMaturityLevels = _context.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + // get the target maturity level IDs + var targetRange = new ACETMaturityBusiness(_context, _assessmentUtil, _adminTabBusiness).GetIseMaturityRangeIds(_assessmentId); + + var questions = _context.MATURITY_QUESTIONS.Where(q => + myModel.model_id == q.Maturity_Model_Id).ToList(); + + + // Get all MATURITY answers for the assessment + var answers = from a in _context.ANSWER.Where(x => x.Assessment_Id == _assessmentId && x.Question_Type == "Maturity") + from b in _context.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() + select new FullAnswer() { a = a, b = b }; + + + // Get all subgroupings for this maturity model + var allGroupings = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id).ToList(); + + //Get All the Observations and issues with the Observations. + + + // Recursively build the grouping/question hierarchy + var questionGrouping = new MaturityGrouping(); + BuildSubGroupings(questionGrouping, null, allGroupings, questions, answers.ToList()); + + var maturityDomains = new List(); + + // ToDo: Refactor the following stucture of loops + foreach (var domain in questionGrouping.SubGroupings) + { + var newDomain = new MatAnsweredQuestionDomain() + { + Title = domain.Title, + IsDeficient = false, + AssessmentFactors = new List() + }; + foreach (var assesmentFactor in domain.SubGroupings) + { + var newAssesmentFactor = new MaturityAnsweredQuestionsAssesment() + { + Title = assesmentFactor.Title, + IsDeficient = false, + Components = new List() + }; + + foreach (var componenet in assesmentFactor.SubGroupings) + { + var newComponent = new MaturityAnsweredQuestionsComponent() + { + Title = componenet.Title, + IsDeficient = false, + Questions = new List() + }; + + foreach (var question in componenet.Questions) + { + if (question.Answer != null) + { + var newQuestion = new MaturityAnsweredQuestions() + { + Title = question.DisplayNumber, + QuestionText = question.QuestionText, + MaturityLevel = GetLevelLabel(question.MaturityLevel, myMaturityLevels), + AnswerText = question.Answer, + Comment = question.Comment, + MarkForReview = question.MarkForReview, + MatQuestionId = question.QuestionId, + FreeResponseText = question.FreeResponseAnswer + }; + + if (question.Answer == "N") + { + newDomain.IsDeficient = true; + newAssesmentFactor.IsDeficient = true; + newComponent.IsDeficient = true; + } + + if (question.Comment != null) + { + newQuestion.Comments = "Yes"; + } + else + { + newQuestion.Comments = "No"; + } + + newComponent.Questions.Add(newQuestion); + } + } + if (newComponent.Questions.Count > 0) + { + newAssesmentFactor.Components.Add(newComponent); + } + } + if (newAssesmentFactor.Components.Count > 0) + { + newDomain.AssessmentFactors.Add(newAssesmentFactor); + } + } + if (newDomain.AssessmentFactors.Count > 0) + { + maturityDomains.Add(newDomain); + } + } + + return maturityDomains; + } + + + /// + /// Returns a block of data generally from the INFORMATION table plus a few others. + /// + /// + public BasicReportData.INFORMATION GetIseInformation() + { + INFORMATION infodb = _context.INFORMATION.Where(x => x.Id == _assessmentId).FirstOrDefault(); + + TinyMapper.Bind(config => + { + config.Ignore(x => x.Additional_Contacts); + }); + var info = TinyMapper.Map(infodb); + + var assessment = _context.ASSESSMENTS.FirstOrDefault(x => x.Assessment_Id == _assessmentId); + info.Assessment_Date = assessment.Assessment_Date; + + info.Assessment_Effective_Date = assessment.AssessmentEffectiveDate; + info.Assessment_Creation_Date = assessment.AssessmentCreatedDate; + + // Primary Assessor + var user = _context.USERS.FirstOrDefault(x => x.UserId == assessment.AssessmentCreatorId); + info.Assessor_Name = user != null ? FormatName(user.FirstName, user.LastName) : string.Empty; + + + // Other Contacts + info.Additional_Contacts = new List(); + var contacts = _context.ASSESSMENT_CONTACTS + .Where(ac => ac.Assessment_Id == _assessmentId + && ac.UserId != assessment.AssessmentCreatorId) + .Include(u => u.User) + .ToList(); + foreach (var c in contacts) + { + info.Additional_Contacts.Add(FormatName(c.FirstName, c.LastName)); + } + + // Include anything that was in the INFORMATION record's Additional_Contacts column + if (infodb.Additional_Contacts != null) + { + string[] acLines = infodb.Additional_Contacts.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); + foreach (string c in acLines) + { + info.Additional_Contacts.Add(c); + } + } + + info.UseStandard = assessment.UseStandard; + info.UseMaturity = assessment.UseMaturity; + info.UseDiagram = assessment.UseDiagram; + + // ACET properties + info.Credit_Union_Name = assessment.CreditUnionName; + info.Charter = assessment.Charter; + + info.Assets = 0; + bool a = long.TryParse(assessment.Assets, out long assets); + if (a) + { + info.Assets = assets; + } + + // Maturity properties + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .FirstOrDefault(x => x.Assessment_Id == _assessmentId); + if (myModel != null) + { + info.QuestionsAlias = myModel.model.Questions_Alias; + } + + return info; + } + + + public List GetIseSourceFiles() + { + + var data = (from g in _context.GEN_FILE + join a in _context.MATURITY_REFERENCES + on g.Gen_File_Id equals a.Gen_File_Id + join q in _context.MATURITY_QUESTIONS + on a.Mat_Question_Id equals q.Mat_Question_Id + where q.Maturity_Model_Id == 10 && a.Source + select new { a, q, g }).ToList(); + + List result = new List(); + SourceFiles file = new SourceFiles(); + foreach (var item in data) + { + try + { + file.Mat_Question_Id = item.q.Mat_Question_Id; + file.Gen_File_Id = item.g.Gen_File_Id; + file.Title = item.g.Title; + } + catch + { + + } + result.Add(file); + + } + + return result; + + } + } +} \ No newline at end of file diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs index 7ad8ab03fc..2b1cb32b32 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs @@ -4,9 +4,12 @@ // // //////////////////////////////// - +using CSETWebCore.Business.Acet; +using CSETWebCore.Business.Maturity; +using CSETWebCore.Business.Maturity.Configuration; using CSETWebCore.Business.Question; using CSETWebCore.Business.Sal; +using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; using CSETWebCore.Helpers; using CSETWebCore.Interfaces.AdminTab; @@ -15,22 +18,30 @@ using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; using CSETWebCore.Model.Diagram; +using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; using CSETWebCore.Model.Reports; +using CSETWebCore.Model.Set; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Nelibur.ObjectMapper; using Snickler.EFCore; using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; +using System.Runtime.Intrinsics.Arm; +using System.Text.RegularExpressions; using System.Threading.Tasks; +using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports { public partial class ReportsDataBusiness : IReportsDataBusiness - { + { private readonly CSETContext _context; private readonly IAssessmentUtil _assessmentUtil; private int _assessmentId; @@ -74,90 +85,214 @@ public void SetReportsAssessmentId(int assessmentId) /// - /// Primarily used for ACET which uses strings to describe their levels + /// Returns an unfiltered list of MatRelevantAnswers for the current assessment. + /// The optional modelId parameter is used to get a specific model's questions. If not + /// supplied, the default model's questions are retrieved. /// - /// /// - private string GetLevelLabel(int maturityLevel, List levels) + public List GetQuestionsList(int? modelId = null) { - return levels.FirstOrDefault(x => x.Maturity_Level_Id == maturityLevel)?.Level_Name ?? ""; + int targetModelId = 0; + + if (modelId == null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + if (myModel == null) + { + return new List(); + } + + targetModelId = myModel.model_id; + } + else + { + targetModelId = (int)modelId; + } + + + var lang = _tokenManager.GetCurrentLanguage(); + + _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); + + // flesh out model-specific questions + if (modelId != null) + { + _context.FillEmptyMaturityQuestionsForModel(_assessmentId, (int)modelId); + } + + var query = from a in _context.ANSWER + join m in _context.MATURITY_QUESTIONS.Include(x => x.Maturity_Level) + on a.Question_Or_Requirement_Id equals m.Mat_Question_Id + where a.Assessment_Id == _assessmentId + && m.Maturity_Model_Id == targetModelId + && a.Question_Type == "Maturity" + && !this.OutOfScopeQuestions.Contains(m.Mat_Question_Id) + orderby m.Grouping_Id, m.Maturity_Level_Id, m.Mat_Question_Id ascending + select new MatRelevantAnswers() + { + ANSWER = a, + Mat = m + }; + + var responseList = query.ToList(); + var childQuestions = responseList.FindAll(x => x.Mat.Parent_Question_Id != null); + + // Set IsParentWithChildren property for all parent questions that have child questions + foreach (var matAns in responseList) + { + if (childQuestions.Exists(x => x.Mat.Parent_Question_Id == matAns.Mat.Mat_Question_Id)) + { + matAns.IsParentWithChildren = true; + } + } + + foreach (var matAns in responseList) + { + var o = _overlay.GetMaturityQuestion(matAns.Mat.Mat_Question_Id, lang); + if (o != null) + { + matAns.Mat.Question_Title = o.QuestionTitle ?? matAns.Mat.Question_Title; + matAns.Mat.Question_Text = o.QuestionText; + matAns.Mat.Supplemental_Info = o.SupplementalInfo; + } + } + + + // if a maturity level is defined, only report on questions at or below that level + int? selectedLevel = _context.ASSESSMENT_SELECTED_LEVELS.Where(x => x.Assessment_Id == _assessmentId + && x.Level_Name == Constants.Constants.MaturityLevel).Select(x => int.Parse(x.Standard_Specific_Sal_Level)).FirstOrDefault(); + + NullOutNavigationPropeties(responseList); + + // RRA should be always be defaulted to its maximum available level (3) + // since the user can't configure it + if (targetModelId == 5) + { + selectedLevel = 3; + } + + if (selectedLevel != null && selectedLevel != 0) + { + responseList = responseList.Where(x => x.Mat.Maturity_Level.Level <= selectedLevel).ToList(); + } + + + return responseList; } + /// - /// Returns a block of data generally from the INFORMATION table plus a few others. + /// Returns a list of MatRelevantAnswers that are considered deficient for the assessment. /// /// - public BasicReportData.INFORMATION GetIseInformation() + public List GetMaturityDeficiencies(int? modelId = null) { - INFORMATION infodb = _context.INFORMATION.Where(x => x.Id == _assessmentId).FirstOrDefault(); + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - TinyMapper.Bind(config => + var targetModel = myModel.model; + + + // if a model was explicitly requested, do that one + if (modelId != null) { - config.Ignore(x => x.Additional_Contacts); - }); - var info = TinyMapper.Map(infodb); + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); + } - var assessment = _context.ASSESSMENTS.FirstOrDefault(x => x.Assessment_Id == _assessmentId); - info.Assessment_Date = assessment.Assessment_Date; - info.Assessment_Effective_Date = assessment.AssessmentEffectiveDate; - info.Assessment_Creation_Date = assessment.AssessmentCreatedDate; + bool ignoreParentQuestions = false; - // Primary Assessor - var user = _context.USERS.FirstOrDefault(x => x.UserId == assessment.AssessmentCreatorId); - info.Assessor_Name = user != null ? FormatName(user.FirstName, user.LastName) : string.Empty; + // default answer values that are considered 'deficient' (in case we can't find a model config profile) + List deficientAnswerValues = new List() { "N", "U" }; - // Other Contacts - info.Additional_Contacts = new List(); - var contacts = _context.ASSESSMENT_CONTACTS - .Where(ac => ac.Assessment_Id == _assessmentId - && ac.UserId != assessment.AssessmentCreatorId) - .Include(u => u.User) - .ToList(); - foreach (var c in contacts) + // try to get a configuration for the actual model + var modelProperties = new ModelProfile().GetModelProperties(targetModel.Maturity_Model_Id); + if (modelProperties != null) { - info.Additional_Contacts.Add(FormatName(c.FirstName, c.LastName)); + deficientAnswerValues = modelProperties.DeficientAnswers; + ignoreParentQuestions = modelProperties.IgnoreParentQuestions; } - // Include anything that was in the INFORMATION record's Additional_Contacts column - if (infodb.Additional_Contacts != null) + + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => deficientAnswerValues.Contains(x.ANSWER.Answer_Text)).ToList(); + + + // We don't consider parent questions that have children to be unanswered for certain maturity models + // (i.e. for CRR, EDM since they just house the question extras) + if (ignoreParentQuestions) { - string[] acLines = infodb.Additional_Contacts.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); - foreach (string c in acLines) - { - info.Additional_Contacts.Add(c); - } + responseList = responseList.Where(x => !x.IsParentWithChildren).ToList(); } - info.UseStandard = assessment.UseStandard; - info.UseMaturity = assessment.UseMaturity; - info.UseDiagram = assessment.UseDiagram; - // ACET properties - info.Credit_Union_Name = assessment.CreditUnionName; - info.Charter = assessment.Charter; + // If the assessment is using a submodel, only keep the submodel's subset of questions + var maturitySubmodel = _context.DETAILS_DEMOGRAPHICS.Where(x => x.Assessment_Id == _assessmentId && x.DataItemName == "MATURITY-SUBMODEL").FirstOrDefault(); + if (maturitySubmodel != null) + { + var whitelist = _context.MATURITY_SUB_MODEL_QUESTIONS.Where(x => x.Sub_Model_Name == maturitySubmodel.StringValue).Select(q => q.Mat_Question_Id).ToList(); + responseList = responseList.Where(x => whitelist.Contains(x.Mat.Mat_Question_Id)).ToList(); + } - info.Assets = 0; - bool a = long.TryParse(assessment.Assets, out long assets); - if (a) + return responseList; + } + + + + /// + /// Returns a list of MatRelevantAnswers that contain comments. + /// + /// + public List GetCommentsList(int? modelId = null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var targetModel = myModel.model; + + // if a model was explicitly requested, do that one + if (modelId != null) { - info.Assets = assets; + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); } - // Maturity properties - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .FirstOrDefault(x => x.Assessment_Id == _assessmentId); - if (myModel != null) + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => !string.IsNullOrWhiteSpace(x.ANSWER.Comment)).ToList(); + + return responseList; + } + + + /// + /// Returns a list of MatRelevantAnswers that are marked for review. + /// + /// + /// + public List GetMarkedForReviewList(int? modelId = null) + { + var myModel = _context.AVAILABLE_MATURITY_MODELS.Include(x => x.model).Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + var targetModel = myModel.model; + + // if a model was explicitly requested, do that one + if (modelId != null) { - info.QuestionsAlias = myModel.model.Questions_Alias; + targetModel = _context.MATURITY_MODELS.Where(x => x.Maturity_Model_Id == modelId).FirstOrDefault(); } - return info; + var responseList = GetQuestionsList(targetModel.Maturity_Model_Id).Where(x => x.ANSWER.Mark_For_Review ?? false).ToList(); + + return responseList; } + /// + /// Returns a list of MatRelevantAnswers that have been answered "A". + /// + /// + public List GetAlternatesList() + { + var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); + return responseList; + } + /// /// Returns a list of domains for the assessment. /// @@ -371,7 +506,7 @@ join a in _context.Answer_Requirements on r.Requirement_Id equals a.Question_Or_ var c = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Category.ToLower(), lang); var s = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Sub_Category.ToLower(), lang); - + // Replace parameter in requirement text if custom parameter is found a.Requirement_Text = rm.ResolveParameters(a.Requirement_Id, a.Answer_Id, a.Requirement_Text); @@ -609,7 +744,7 @@ public async Task> GetStandardQuestionAnswers(int assess StandardShortName = a.ShortName }); } - lastshortname = a.ShortName; + lastshortname = a.ShortName; qlist.Add(new SimpleStandardQuestions() { ShortName = a.ShortName, @@ -944,7 +1079,7 @@ public List GetRankedQuestions() } public List GetQuestionsWithSupplementals() - { + { var lang = _tokenManager.GetCurrentLanguage(); var rm = new Question.RequirementBusiness(_assessmentUtil, _questionRequirement, _context, _tokenManager); @@ -954,9 +1089,9 @@ public List GetQuestionsWithSupplementals() var supplementalLookups = (from a in _context.NEW_REQUIREMENT - join b in _context.REQUIREMENT_SETS on a.Requirement_Id equals b.Requirement_Id - where b.Set_Name == "MOPhysical" - select a).ToDictionary(x=> x.Requirement_Id, x=> x); + join b in _context.REQUIREMENT_SETS on a.Requirement_Id equals b.Requirement_Id + where b.Set_Name == "MOPhysical" + select a).ToDictionary(x => x.Requirement_Id, x => x); foreach (usp_GetRankedQuestions_Result q in rankedQuestionList) { @@ -967,7 +1102,7 @@ join b in _context.REQUIREMENT_SETS on a.Requirement_Id equals b.Requirement_Id { q.QuestionText = reqOverlay.RequirementText; } - + } @@ -975,7 +1110,7 @@ join b in _context.REQUIREMENT_SETS on a.Requirement_Id equals b.Requirement_Id q.Category = _overlay.GetPropertyValue("STANDARD_CATEGORY", q.Category.ToLower(), lang) ?? q.Category; var comment = _context.Answer_Requirements.Where(x => x.Question_Or_Requirement_Id == q.QuestionOrRequirementID).FirstOrDefault()?.Comment; - var supplemental = supplementalLookups[q.RequirementId??0].Supplemental_Info; + var supplemental = supplementalLookups[q.RequirementId ?? 0].Supplemental_Info; list.Add(new PhysicalQuestions() { Answer = q.AnswerText, @@ -1345,48 +1480,6 @@ private void GetQuestionTitleAndText(dynamic f, } - /// - /// Formats the Title for CIE observations the way they want - /// - /// - private void GetQuestionTitleAndTextForCie(dynamic f, - List stdList, List compList, - int answerId, - out string identifier, out string questionText) - { - identifier = ""; - questionText = ""; - var lang = _tokenManager.GetCurrentLanguage(); - - identifier = f.mq.Question_Title; - questionText = f.mq.Question_Text; - int groupId = f.mq.Grouping_Id ?? 0; - - var groupRow = _context.MATURITY_GROUPINGS.Where(x => x.Grouping_Id == groupId).FirstOrDefault(); - int principleNumber = 0; - int phaseNumber = 0; - - if (groupRow.Group_Level == 2) - { - // tracking the principle number - principleNumber = groupRow.Sequence; - identifier = "Principle " + principleNumber + " - " + identifier; - } - else if (groupRow.Group_Level == 3) - { - // tracking the phase number - // the -1 is because the "General" grouping is first at Sequence = 1, but it's hidden from the user for now (request from the client) - phaseNumber = groupRow.Sequence - 1; - - // finding the principle number - groupRow = _context.MATURITY_GROUPINGS.Where(x => x.Grouping_Id == groupRow.Parent_Id).FirstOrDefault(); - principleNumber = groupRow.Sequence; - - identifier = "Principle " + principleNumber + " - Phase " + phaseNumber + " - " + identifier; - } - } - - /// /// /// @@ -1443,6 +1536,73 @@ join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id } + /// + /// + /// + /// + public List GetMaturityModelData() + { + List mat_questions = new List(); + List mat_models = new List(); + + _context.FillEmptyMaturityQuestionsForAnalysis(_assessmentId); + + var query = ( + from amm in _context.AVAILABLE_MATURITY_MODELS + join mm in _context.MATURITY_MODELS on amm.model_id equals mm.Maturity_Model_Id + join mq in _context.MATURITY_QUESTIONS on mm.Maturity_Model_Id equals mq.Maturity_Model_Id + join ans in _context.ANSWER on mq.Mat_Question_Id equals ans.Question_Or_Requirement_Id + join asl in _context.ASSESSMENT_SELECTED_LEVELS on amm.Assessment_Id equals asl.Assessment_Id + where amm.Assessment_Id == _assessmentId + && ans.Assessment_Id == _assessmentId + && ans.Is_Maturity == true + && asl.Level_Name == Constants.Constants.MaturityLevel + select new { amm, mm, mq, ans, asl } + ).ToList(); + var models = query.Select(x => new { x.mm, x.asl }).Distinct(); + foreach (var model in models) + { + MaturityReportData.MaturityModel newModel = new MaturityReportData.MaturityModel(); + newModel.MaturityModelName = model.mm.Model_Name; + newModel.MaturityModelID = model.mm.Maturity_Model_Id; + if (Int32.TryParse(model.asl.Standard_Specific_Sal_Level, out int lvl)) + { + newModel.TargetLevel = lvl; + } + else + { + newModel.TargetLevel = null; + } + mat_models.Add(newModel); + } + + foreach (var queryItem in query) + { + MaturityQuestion newQuestion = new MaturityQuestion(); + newQuestion.Mat_Question_Id = queryItem.mq.Mat_Question_Id; + newQuestion.Question_Title = queryItem.mq.Question_Title; + newQuestion.Question_Text = queryItem.mq.Question_Text; + newQuestion.Supplemental_Info = queryItem.mq.Supplemental_Info; + newQuestion.Examination_Approach = queryItem.mq.Examination_Approach; + newQuestion.Grouping_Id = queryItem.mq.Grouping_Id ?? 0; + newQuestion.Parent_Question_Id = queryItem.mq.Parent_Question_Id; + newQuestion.Maturity_Level = queryItem.mq.Maturity_Level_Id; + newQuestion.Set_Name = queryItem.mm.Model_Name; + newQuestion.Sequence = queryItem.mq.Sequence; + newQuestion.Maturity_Model_Id = queryItem.mm.Maturity_Model_Id; + newQuestion.Answer = queryItem.ans; + + mat_models.Where(x => x.MaturityModelID == newQuestion.Maturity_Model_Id) + .FirstOrDefault() + .MaturityQuestions.Add(newQuestion); + + mat_questions.Add(newQuestion); + } + + return mat_models; + } + + /// /// Formats first and last name. If the name is believed to be a domain\userid, /// the userid is returned with the domain removed. @@ -1504,47 +1664,14 @@ private void NullOutNavigationPropeties(List list) } } - public List GetIseSourceFiles() - { - - var data = (from g in _context.GEN_FILE - join a in _context.MATURITY_REFERENCES - on g.Gen_File_Id equals a.Gen_File_Id - join q in _context.MATURITY_QUESTIONS - on a.Mat_Question_Id equals q.Mat_Question_Id - where q.Maturity_Model_Id == 10 && a.Source - select new { a, q, g }).ToList(); - - List result = new List(); - SourceFiles file = new SourceFiles(); - foreach (var item in data) - { - try - { - file.Mat_Question_Id = item.q.Mat_Question_Id; - file.Gen_File_Id = item.g.Gen_File_Id; - file.Title = item.g.Title; - } - catch - { - - } - result.Add(file); - - } - - return result; - - } - public string GetCsetVersion() { return _context.CSET_VERSION.Select(x => x.Cset_Version1).FirstOrDefault(); } + public string GetAssessmentGuid(int assessmentId) { return _context.ASSESSMENTS.Where(x => x.Assessment_Id == assessmentId).Select(x => x.Assessment_GUID).FirstOrDefault().ToString(); } - } -} +} \ No newline at end of file From 93c154efa12fae45afb4dd143270deb9d1ea9a6b Mon Sep 17 00:00:00 2001 From: Mostafa Abdo Date: Wed, 4 Dec 2024 16:48:42 -0800 Subject: [PATCH 3/5] factor out utils methods --- .../ReportsData/ReportsDataBusiness.cs | 373 ---------------- .../Reports/ReportsData/ReportsUtils.cs | 419 ++++++++++++++++++ 2 files changed, 419 insertions(+), 373 deletions(-) create mode 100644 CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs index 2b1cb32b32..275049763c 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs @@ -74,16 +74,6 @@ public ReportsDataBusiness(CSETContext context, IAssessmentUtil assessmentUtil, } - /// - /// - /// - /// - public void SetReportsAssessmentId(int assessmentId) - { - _assessmentId = assessmentId; - } - - /// /// Returns an unfiltered list of MatRelevantAnswers for the current assessment. /// The optional modelId parameter is used to get a specific model's questions. If not @@ -283,35 +273,6 @@ public List GetMarkedForReviewList(int? modelId = null) } - /// - /// Returns a list of MatRelevantAnswers that have been answered "A". - /// - /// - public List GetAlternatesList() - { - var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); - return responseList; - } - - /// - /// Returns a list of domains for the assessment. - /// - /// - public List GetDomains() - { - var myModel = _context.AVAILABLE_MATURITY_MODELS - .Include(x => x.model) - .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); - - // Get all domains for this maturity model - var domains = _context.MATURITY_GROUPINGS - .Include(x => x.Type) - .Where(x => x.Maturity_Model_Id == myModel.model_id && x.Type_Id == 1).ToList(); - - return domains.Select(d => d.Title).ToList(); - } - - /// /// /// @@ -394,163 +355,6 @@ public void BuildSubGroupings(MaturityGrouping g, int? parentID, } - /// - /// - /// - /// - public List GetControls(string applicationMode) - { - var lang = _tokenManager.GetCurrentLanguage(); - var rm = new Question.RequirementBusiness(_assessmentUtil, _questionRequirement, _context, _tokenManager); - - _questionRequirement.InitializeManager(_assessmentId); - - _context.FillEmptyQuestionsForAnalysis(_assessmentId); - - string level = _questionRequirement.StandardLevel == null ? "L" : _questionRequirement.StandardLevel; - - List controlRows = new List(); - - if (applicationMode == CSETWebCore.Business.Assessment.AssessmentMode.QUESTIONS_BASED_APPLICATION_MODE) - { - var qQ = (from rs in _context.REQUIREMENT_SETS - join r in _context.NEW_REQUIREMENT on rs.Requirement_Id equals r.Requirement_Id - join rl in _context.REQUIREMENT_LEVELS on r.Requirement_Id equals rl.Requirement_Id - join s in _context.SETS on rs.Set_Name equals s.Set_Name - join av in _context.AVAILABLE_STANDARDS on s.Set_Name equals av.Set_Name - join rqs in _context.REQUIREMENT_QUESTIONS_SETS on new { r.Requirement_Id, s.Set_Name } equals new { rqs.Requirement_Id, rqs.Set_Name } - join qu in _context.NEW_QUESTION on rqs.Question_Id equals qu.Question_Id - join a in _context.Answer_Questions_No_Components on qu.Question_Id equals a.Question_Or_Requirement_Id - where rl.Standard_Level == level && av.Selected == true && rl.Level_Type == "NST" - && av.Assessment_Id == _assessmentId && a.Assessment_Id == _assessmentId - orderby r.Standard_Category, r.Standard_Sub_Category, rs.Requirement_Sequence - select new { r, rl, s, qu, a }).ToList(); - - foreach (var q in qQ) - { - controlRows.Add(new ControlRow() - { - Requirement_Id = q.r.Requirement_Id, - Requirement_Text = q.r.Requirement_Text, - Answer_Text = q.a.Answer_Text, - Comment = q.a.Comment, - Question_Id = q.qu.Question_Id, - Requirement_Title = q.r.Requirement_Title, - Short_Name = q.s.Short_Name, - Simple_Question = q.qu.Simple_Question, - Standard_Category = q.r.Standard_Category, - Standard_Sub_Category = q.r.Standard_Sub_Category, - Standard_Level = q.rl.Standard_Level - }); - } - } - else - { - var qR = (from rs in _context.REQUIREMENT_SETS - join r in _context.NEW_REQUIREMENT on rs.Requirement_Id equals r.Requirement_Id - join rl in _context.REQUIREMENT_LEVELS on r.Requirement_Id equals rl.Requirement_Id - join s in _context.SETS on rs.Set_Name equals s.Set_Name - join av in _context.AVAILABLE_STANDARDS on s.Set_Name equals av.Set_Name - join rqs in _context.REQUIREMENT_QUESTIONS_SETS on new { r.Requirement_Id, s.Set_Name } equals new { rqs.Requirement_Id, rqs.Set_Name } - join qu in _context.NEW_QUESTION on rqs.Question_Id equals qu.Question_Id - join a in _context.Answer_Requirements on r.Requirement_Id equals a.Question_Or_Requirement_Id - where rl.Standard_Level == level && av.Selected == true && rl.Level_Type == "NST" - && av.Assessment_Id == _assessmentId && a.Assessment_Id == _assessmentId - orderby r.Standard_Category, r.Standard_Sub_Category, rs.Requirement_Sequence - select new { r, rl, s, qu, a }).ToList(); - - foreach (var q in qR) - { - controlRows.Add(new ControlRow() - { - Requirement_Id = q.a.Question_Or_Requirement_Id, - Requirement_Text = q.r.Requirement_Text, - Answer_Text = q.a.Answer_Text, - Comment = q.a.Comment, - Question_Id = q.qu.Question_Id, - Requirement_Title = q.r.Requirement_Title, - Short_Name = q.s.Short_Name, - Simple_Question = q.qu.Simple_Question, - Standard_Category = q.r.Standard_Category, - Standard_Sub_Category = q.r.Standard_Sub_Category, - Standard_Level = q.rl.Standard_Level, - Answer_Id = q.a.Answer_Id - }); - } - } - - - - //get all the questions for this control - //determine the percent implemented. - int prev_requirement_id = 0; - int questionCount = 0; - int questionsAnswered = 0; - BasicReportData.RequirementControl control = null; - List questions = null; - - // The response - List controls = []; - - foreach (var a in controlRows) - { - if (prev_requirement_id != a.Requirement_Id) - { - questionCount = 0; - questionsAnswered = 0; - questions = new List(); - - - // look for translations - var r = _overlay.GetRequirement(a.Requirement_Id, lang); - var c = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Category.ToLower(), lang); - var s = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Sub_Category.ToLower(), lang); - - - // Replace parameter in requirement text if custom parameter is found - a.Requirement_Text = rm.ResolveParameters(a.Requirement_Id, a.Answer_Id, a.Requirement_Text); - - control = new BasicReportData.RequirementControl() - { - ControlDescription = r?.RequirementText ?? a.Requirement_Text, - RequirementTitle = a.Requirement_Title, - Level = a.Standard_Level, - StandardShortName = a.Short_Name, - Standard_Category = c ?? a.Standard_Category, - SubCategory = s ?? a.Standard_Sub_Category, - Control_Questions = questions - }; - - - - controls.Add(control); - } - - questionCount++; - - switch (a.Answer_Text) - { - case Constants.Constants.ALTERNATE: - case Constants.Constants.YES: - questionsAnswered++; - break; - } - - questions.Add(new BasicReportData.Control_Questions() - { - Answer = a.Answer_Text, - Comment = a.Comment, - Simple_Question = a.Simple_Question - }); - - control.ImplementationStatus = StatUtils.Percentagize(questionsAnswered, questionCount, 2).ToString("##.##"); - prev_requirement_id = a.Requirement_Id; - } - - return controls; - } - - /// /// /// @@ -1127,32 +931,6 @@ join b in _context.REQUIREMENT_SETS on a.Requirement_Id equals b.Requirement_Id } - public List GetDocumentLibrary() - { - List list = new List(); - var docs = from a in _context.DOCUMENT_FILE - where a.Assessment_Id == _assessmentId - select a; - foreach (var doc in docs) - { - var dlt = new DocumentLibraryTable() - { - DocumentTitle = doc.Title, - FileName = doc.Path - }; - - if (dlt.DocumentTitle == "click to edit title") - { - dlt.DocumentTitle = "(untitled)"; - } - - list.Add(dlt); - } - - return list; - } - - public BasicReportData.OverallSALTable GetNistSals() { var manager = new NistSalBusiness(_context, _assessmentUtil, _tokenManager); @@ -1400,86 +1178,6 @@ join b in _context.ASSESSMENT_CONTACTS on a.Assessment_Contact_Id equals b.Asses } - /// - /// Formats an identifier for the corresponding question. - /// Also returns the question text with parameters applied, in the - /// case of a requirement. - /// - /// If the user's language is non-English, attempts to overlay the - /// question text with the translated version. - /// - /// - private void GetQuestionTitleAndText(dynamic f, - List stdList, List compList, - int answerId, - out string identifier, out string questionText) - { - identifier = ""; - questionText = ""; - var lang = _tokenManager.GetCurrentLanguage(); - - switch (f.c.Question_Type) - { - case "Question": - foreach (var s in stdList) - { - var q1 = s.Questions.FirstOrDefault(x => x.QuestionId == f.c.Question_Or_Requirement_Id); - if (q1 != null) - { - identifier = q1.CategoryAndNumber; - questionText = q1.Question; - return; - } - } - - return; - - case "Component": - var q2 = compList.FirstOrDefault(x => x.QuestionId == f.c.Question_Or_Requirement_Id); - if (q2 != null) - { - identifier = q2.ComponentName; - questionText = q2.Question; - } - - return; - - case "Requirement": - identifier = f.r.Requirement_Title; - var rb = new RequirementBusiness(_assessmentUtil, _questionRequirement, _context, _tokenManager); - questionText = rb.ResolveParameters(f.r.Requirement_Id, answerId, f.r.Requirement_Text); - - // translate - questionText = _overlay.GetRequirement(f.r.Requirement_Id, lang)?.RequirementText ?? questionText; - - return; - - case "Maturity": - - identifier = f.mq.Question_Title; - questionText = f.mq.Question_Text; - - // CPG is a special case - if (!String.IsNullOrEmpty(f.mq.Security_Practice)) - { - questionText = f.mq.Security_Practice; - } - - // overlay - MaturityQuestionOverlay o = _overlay.GetMaturityQuestion(f.mq.Mat_Question_Id, lang); - if (o != null) - { - identifier = o.QuestionTitle; - questionText = o.QuestionText; - } - return; - - default: - return; - } - } - - /// /// /// @@ -1602,76 +1300,5 @@ join asl in _context.ASSESSMENT_SELECTED_LEVELS on amm.Assessment_Id equals asl. return mat_models; } - - /// - /// Formats first and last name. If the name is believed to be a domain\userid, - /// the userid is returned with the domain removed. - /// - /// - /// - /// - public string FormatName(string firstName, string lastName) - { - firstName = firstName.Trim(); - lastName = lastName.Trim(); - - if (firstName.Length > 0 && lastName.Length > 0) - { - return string.Format("{0} {1}", firstName, lastName); - } - - // if domain-qualified userid, remove domain - if (firstName.IndexOf('\\') >= 0 && firstName.IndexOf(' ') < 0 && lastName.Length == 0) - { - return firstName.Substring(firstName.LastIndexOf('\\') + 1); - } - - return string.Format("{0} {1}", firstName, lastName); - } - - - /// - /// Gets all confidential types for report generation - /// - /// - public IEnumerable GetConfidentialTypes() - { - return _context.CONFIDENTIAL_TYPE.OrderBy(x => x.ConfidentialTypeOrder); - } - - private void NullOutNavigationPropeties(List list) - { - // null out a few navigation properties to avoid circular references that blow up the JSON stringifier - foreach (MatRelevantAnswers a in list) - { - a.ANSWER.Assessment = null; - a.Mat.Maturity_Model = null; - a.Mat.InverseParent_Question = null; - a.Mat.Parent_Question = null; - - if (a.Mat.Grouping != null) - { - a.Mat.Grouping.Maturity_Model = null; - a.Mat.Grouping.MATURITY_QUESTIONS = null; - a.Mat.Grouping.Type = null; - } - - if (a.Mat.Maturity_Level != null) - { - a.Mat.Maturity_Level.MATURITY_QUESTIONS = null; - a.Mat.Maturity_Level.Maturity_Model = null; - } - } - } - - public string GetCsetVersion() - { - return _context.CSET_VERSION.Select(x => x.Cset_Version1).FirstOrDefault(); - } - - public string GetAssessmentGuid(int assessmentId) - { - return _context.ASSESSMENTS.Where(x => x.Assessment_Id == assessmentId).Select(x => x.Assessment_GUID).FirstOrDefault().ToString(); - } } } \ No newline at end of file diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs new file mode 100644 index 0000000000..ba64e93442 --- /dev/null +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs @@ -0,0 +1,419 @@ +//////////////////////////////// +// +// Copyright 2024 Battelle Energy Alliance, LLC +// +// +//////////////////////////////// +using CSETWebCore.Business.Acet; +using CSETWebCore.Business.Maturity; +using CSETWebCore.Business.Maturity.Configuration; +using CSETWebCore.Business.Question; +using CSETWebCore.Business.Sal; +using CSETWebCore.DataLayer.Manual; +using CSETWebCore.DataLayer.Model; +using CSETWebCore.Helpers; +using CSETWebCore.Interfaces.AdminTab; +using CSETWebCore.Interfaces.Helpers; +using CSETWebCore.Interfaces.Maturity; +using CSETWebCore.Interfaces.Question; +using CSETWebCore.Interfaces.Reports; +using CSETWebCore.Model.Diagram; +using CSETWebCore.Model.Document; +using CSETWebCore.Model.Maturity; +using CSETWebCore.Model.Question; +using CSETWebCore.Model.Reports; +using CSETWebCore.Model.Set; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Nelibur.ObjectMapper; +using Snickler.EFCore; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Runtime.Intrinsics.Arm; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static Lucene.Net.Util.Fst.Util; + + +namespace CSETWebCore.Business.Reports +{ + public partial class ReportsDataBusiness : IReportsDataBusiness + { + + /// + /// + /// + /// + public void SetReportsAssessmentId(int assessmentId) + { + _assessmentId = assessmentId; + } + + + /// + /// Returns a list of MatRelevantAnswers that have been answered "A". + /// + /// + public List GetAlternatesList() + { + var responseList = GetQuestionsList().Where(x => (x.ANSWER.Answer_Text == "A")).ToList(); + return responseList; + } + + /// + /// Returns a list of domains for the assessment. + /// + /// + public List GetDomains() + { + var myModel = _context.AVAILABLE_MATURITY_MODELS + .Include(x => x.model) + .Where(x => x.Assessment_Id == _assessmentId).FirstOrDefault(); + + // Get all domains for this maturity model + var domains = _context.MATURITY_GROUPINGS + .Include(x => x.Type) + .Where(x => x.Maturity_Model_Id == myModel.model_id && x.Type_Id == 1).ToList(); + + return domains.Select(d => d.Title).ToList(); + } + + + /// + /// + /// + /// + public List GetControls(string applicationMode) + { + var lang = _tokenManager.GetCurrentLanguage(); + var rm = new Question.RequirementBusiness(_assessmentUtil, _questionRequirement, _context, _tokenManager); + + _questionRequirement.InitializeManager(_assessmentId); + + _context.FillEmptyQuestionsForAnalysis(_assessmentId); + + string level = _questionRequirement.StandardLevel == null ? "L" : _questionRequirement.StandardLevel; + + List controlRows = new List(); + + if (applicationMode == CSETWebCore.Business.Assessment.AssessmentMode.QUESTIONS_BASED_APPLICATION_MODE) + { + var qQ = (from rs in _context.REQUIREMENT_SETS + join r in _context.NEW_REQUIREMENT on rs.Requirement_Id equals r.Requirement_Id + join rl in _context.REQUIREMENT_LEVELS on r.Requirement_Id equals rl.Requirement_Id + join s in _context.SETS on rs.Set_Name equals s.Set_Name + join av in _context.AVAILABLE_STANDARDS on s.Set_Name equals av.Set_Name + join rqs in _context.REQUIREMENT_QUESTIONS_SETS on new { r.Requirement_Id, s.Set_Name } equals new { rqs.Requirement_Id, rqs.Set_Name } + join qu in _context.NEW_QUESTION on rqs.Question_Id equals qu.Question_Id + join a in _context.Answer_Questions_No_Components on qu.Question_Id equals a.Question_Or_Requirement_Id + where rl.Standard_Level == level && av.Selected == true && rl.Level_Type == "NST" + && av.Assessment_Id == _assessmentId && a.Assessment_Id == _assessmentId + orderby r.Standard_Category, r.Standard_Sub_Category, rs.Requirement_Sequence + select new { r, rl, s, qu, a }).ToList(); + + foreach (var q in qQ) + { + controlRows.Add(new ControlRow() + { + Requirement_Id = q.r.Requirement_Id, + Requirement_Text = q.r.Requirement_Text, + Answer_Text = q.a.Answer_Text, + Comment = q.a.Comment, + Question_Id = q.qu.Question_Id, + Requirement_Title = q.r.Requirement_Title, + Short_Name = q.s.Short_Name, + Simple_Question = q.qu.Simple_Question, + Standard_Category = q.r.Standard_Category, + Standard_Sub_Category = q.r.Standard_Sub_Category, + Standard_Level = q.rl.Standard_Level + }); + } + } + else + { + var qR = (from rs in _context.REQUIREMENT_SETS + join r in _context.NEW_REQUIREMENT on rs.Requirement_Id equals r.Requirement_Id + join rl in _context.REQUIREMENT_LEVELS on r.Requirement_Id equals rl.Requirement_Id + join s in _context.SETS on rs.Set_Name equals s.Set_Name + join av in _context.AVAILABLE_STANDARDS on s.Set_Name equals av.Set_Name + join rqs in _context.REQUIREMENT_QUESTIONS_SETS on new { r.Requirement_Id, s.Set_Name } equals new { rqs.Requirement_Id, rqs.Set_Name } + join qu in _context.NEW_QUESTION on rqs.Question_Id equals qu.Question_Id + join a in _context.Answer_Requirements on r.Requirement_Id equals a.Question_Or_Requirement_Id + where rl.Standard_Level == level && av.Selected == true && rl.Level_Type == "NST" + && av.Assessment_Id == _assessmentId && a.Assessment_Id == _assessmentId + orderby r.Standard_Category, r.Standard_Sub_Category, rs.Requirement_Sequence + select new { r, rl, s, qu, a }).ToList(); + + foreach (var q in qR) + { + controlRows.Add(new ControlRow() + { + Requirement_Id = q.a.Question_Or_Requirement_Id, + Requirement_Text = q.r.Requirement_Text, + Answer_Text = q.a.Answer_Text, + Comment = q.a.Comment, + Question_Id = q.qu.Question_Id, + Requirement_Title = q.r.Requirement_Title, + Short_Name = q.s.Short_Name, + Simple_Question = q.qu.Simple_Question, + Standard_Category = q.r.Standard_Category, + Standard_Sub_Category = q.r.Standard_Sub_Category, + Standard_Level = q.rl.Standard_Level, + Answer_Id = q.a.Answer_Id + }); + } + } + + + + //get all the questions for this control + //determine the percent implemented. + int prev_requirement_id = 0; + int questionCount = 0; + int questionsAnswered = 0; + BasicReportData.RequirementControl control = null; + List questions = null; + + // The response + List controls = []; + + foreach (var a in controlRows) + { + if (prev_requirement_id != a.Requirement_Id) + { + questionCount = 0; + questionsAnswered = 0; + questions = new List(); + + + // look for translations + var r = _overlay.GetRequirement(a.Requirement_Id, lang); + var c = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Category.ToLower(), lang); + var s = _overlay.GetPropertyValue("STANDARD_CATEGORY", a.Standard_Sub_Category.ToLower(), lang); + + + // Replace parameter in requirement text if custom parameter is found + a.Requirement_Text = rm.ResolveParameters(a.Requirement_Id, a.Answer_Id, a.Requirement_Text); + + control = new BasicReportData.RequirementControl() + { + ControlDescription = r?.RequirementText ?? a.Requirement_Text, + RequirementTitle = a.Requirement_Title, + Level = a.Standard_Level, + StandardShortName = a.Short_Name, + Standard_Category = c ?? a.Standard_Category, + SubCategory = s ?? a.Standard_Sub_Category, + Control_Questions = questions + }; + + + + controls.Add(control); + } + + questionCount++; + + switch (a.Answer_Text) + { + case Constants.Constants.ALTERNATE: + case Constants.Constants.YES: + questionsAnswered++; + break; + } + + questions.Add(new BasicReportData.Control_Questions() + { + Answer = a.Answer_Text, + Comment = a.Comment, + Simple_Question = a.Simple_Question + }); + + control.ImplementationStatus = StatUtils.Percentagize(questionsAnswered, questionCount, 2).ToString("##.##"); + prev_requirement_id = a.Requirement_Id; + } + + return controls; + } + + + public List GetDocumentLibrary() + { + List list = new List(); + var docs = from a in _context.DOCUMENT_FILE + where a.Assessment_Id == _assessmentId + select a; + foreach (var doc in docs) + { + var dlt = new DocumentLibraryTable() + { + DocumentTitle = doc.Title, + FileName = doc.Path + }; + + if (dlt.DocumentTitle == "click to edit title") + { + dlt.DocumentTitle = "(untitled)"; + } + + list.Add(dlt); + } + + return list; + } + + + /// + /// Formats an identifier for the corresponding question. + /// Also returns the question text with parameters applied, in the + /// case of a requirement. + /// + /// If the user's language is non-English, attempts to overlay the + /// question text with the translated version. + /// + /// + private void GetQuestionTitleAndText(dynamic f, + List stdList, List compList, + int answerId, + out string identifier, out string questionText) + { + identifier = ""; + questionText = ""; + var lang = _tokenManager.GetCurrentLanguage(); + + switch (f.c.Question_Type) + { + case "Question": + foreach (var s in stdList) + { + var q1 = s.Questions.FirstOrDefault(x => x.QuestionId == f.c.Question_Or_Requirement_Id); + if (q1 != null) + { + identifier = q1.CategoryAndNumber; + questionText = q1.Question; + return; + } + } + + return; + + case "Component": + var q2 = compList.FirstOrDefault(x => x.QuestionId == f.c.Question_Or_Requirement_Id); + if (q2 != null) + { + identifier = q2.ComponentName; + questionText = q2.Question; + } + + return; + + case "Requirement": + identifier = f.r.Requirement_Title; + var rb = new RequirementBusiness(_assessmentUtil, _questionRequirement, _context, _tokenManager); + questionText = rb.ResolveParameters(f.r.Requirement_Id, answerId, f.r.Requirement_Text); + + // translate + questionText = _overlay.GetRequirement(f.r.Requirement_Id, lang)?.RequirementText ?? questionText; + + return; + + case "Maturity": + + identifier = f.mq.Question_Title; + questionText = f.mq.Question_Text; + + // CPG is a special case + if (!String.IsNullOrEmpty(f.mq.Security_Practice)) + { + questionText = f.mq.Security_Practice; + } + + // overlay + MaturityQuestionOverlay o = _overlay.GetMaturityQuestion(f.mq.Mat_Question_Id, lang); + if (o != null) + { + identifier = o.QuestionTitle; + questionText = o.QuestionText; + } + return; + + default: + return; + } + } + + + /// + /// Formats first and last name. If the name is believed to be a domain\userid, + /// the userid is returned with the domain removed. + /// + /// + /// + /// + public string FormatName(string firstName, string lastName) + { + firstName = firstName.Trim(); + lastName = lastName.Trim(); + + if (firstName.Length > 0 && lastName.Length > 0) + { + return string.Format("{0} {1}", firstName, lastName); + } + + // if domain-qualified userid, remove domain + if (firstName.IndexOf('\\') >= 0 && firstName.IndexOf(' ') < 0 && lastName.Length == 0) + { + return firstName.Substring(firstName.LastIndexOf('\\') + 1); + } + + return string.Format("{0} {1}", firstName, lastName); + } + + + /// + /// Gets all confidential types for report generation + /// + /// + public IEnumerable GetConfidentialTypes() + { + return _context.CONFIDENTIAL_TYPE.OrderBy(x => x.ConfidentialTypeOrder); + } + + private void NullOutNavigationPropeties(List list) + { + // null out a few navigation properties to avoid circular references that blow up the JSON stringifier + foreach (MatRelevantAnswers a in list) + { + a.ANSWER.Assessment = null; + a.Mat.Maturity_Model = null; + a.Mat.InverseParent_Question = null; + a.Mat.Parent_Question = null; + + if (a.Mat.Grouping != null) + { + a.Mat.Grouping.Maturity_Model = null; + a.Mat.Grouping.MATURITY_QUESTIONS = null; + a.Mat.Grouping.Type = null; + } + + if (a.Mat.Maturity_Level != null) + { + a.Mat.Maturity_Level.MATURITY_QUESTIONS = null; + a.Mat.Maturity_Level.Maturity_Model = null; + } + } + } + + public string GetCsetVersion() + { + return _context.CSET_VERSION.Select(x => x.Cset_Version1).FirstOrDefault(); + } + + public string GetAssessmentGuid(int assessmentId) + { + return _context.ASSESSMENTS.Where(x => x.Assessment_Id == assessmentId).Select(x => x.Assessment_GUID).FirstOrDefault().ToString(); + } + } +} \ No newline at end of file From 3ddfd5b2490ec3d4053a72a25ad438417a91077f Mon Sep 17 00:00:00 2001 From: Mostafa Abdo Date: Wed, 4 Dec 2024 16:50:42 -0800 Subject: [PATCH 4/5] resolve unused variable in cmmc warning --- .../CSETWebCore.Business/Maturity/CmmcBusiness.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Maturity/CmmcBusiness.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Maturity/CmmcBusiness.cs index a780a2cc6f..a117b0fa98 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Maturity/CmmcBusiness.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Maturity/CmmcBusiness.cs @@ -22,11 +22,6 @@ public class CmmcBusiness private CSETContext _context; private readonly IAssessmentUtil _assessmentUtil; private readonly IAdminTabBusiness _adminTabBusiness; - - private int _maturityModelId; - - private static object myLock = new object(); - private TranslationOverlay _overlay; private AdditionalSupplemental _addlSuppl; @@ -93,12 +88,12 @@ public int GetScoreForLevel(int assessmentId, int level) var levelId = _context.MATURITY_LEVELS .Where(x => x.Level == level && x.Maturity_Model_Id == modelIdCmmc2) .Select(x => x.Maturity_Level_Id) - .FirstOrDefault(); + .FirstOrDefault(); var query = from a in _context.ANSWER - join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id - where q.Maturity_Level_Id == levelId && a.Assessment_Id == assessmentId - select a; + join q in _context.MATURITY_QUESTIONS on a.Question_Or_Requirement_Id equals q.Mat_Question_Id + where q.Maturity_Level_Id == levelId && a.Assessment_Id == assessmentId + select a; var answerList = query.ToList().Select(x => x.Answer_Text).ToList(); From 5cbddcc44ed60fc42b75072095d52b0865af891b Mon Sep 17 00:00:00 2001 From: Mostafa Abdo Date: Wed, 4 Dec 2024 16:53:37 -0800 Subject: [PATCH 5/5] clean up imports in reports data --- .../Reports/ReportsData/CieReportsData.cs | 24 ------------------- .../Reports/ReportsData/NCUAReportsData.cs | 22 ----------------- .../ReportsData/ReportsDataBusiness.cs | 12 ---------- .../Reports/ReportsData/ReportsUtils.cs | 21 ---------------- 4 files changed, 79 deletions(-) diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs index 424079b21b..84539a2f48 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/CieReportsData.cs @@ -4,38 +4,14 @@ // // //////////////////////////////// -using CSETWebCore.Business.Acet; -using CSETWebCore.Business.Maturity; -using CSETWebCore.Business.Maturity.Configuration; -using CSETWebCore.Business.Question; -using CSETWebCore.Business.Sal; -using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; -using CSETWebCore.Helpers; -using CSETWebCore.Interfaces.AdminTab; -using CSETWebCore.Interfaces.Helpers; -using CSETWebCore.Interfaces.Maturity; -using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; -using CSETWebCore.Model.Diagram; using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; -using CSETWebCore.Model.Reports; -using CSETWebCore.Model.Set; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Nelibur.ObjectMapper; -using Snickler.EFCore; -using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Runtime.Intrinsics.Arm; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs index cb1ac70144..7e9390068f 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/NCUAReportsData.cs @@ -4,38 +4,16 @@ // // //////////////////////////////// -using CSETWebCore.Business.Acet; using CSETWebCore.Business.Maturity; -using CSETWebCore.Business.Maturity.Configuration; -using CSETWebCore.Business.Question; -using CSETWebCore.Business.Sal; -using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; -using CSETWebCore.Helpers; -using CSETWebCore.Interfaces.AdminTab; -using CSETWebCore.Interfaces.Helpers; -using CSETWebCore.Interfaces.Maturity; -using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; -using CSETWebCore.Model.Diagram; -using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; -using CSETWebCore.Model.Reports; -using CSETWebCore.Model.Set; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Nelibur.ObjectMapper; -using Snickler.EFCore; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Runtime.Intrinsics.Arm; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs index 275049763c..2398d2a4da 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsDataBusiness.cs @@ -4,12 +4,8 @@ // // //////////////////////////////// -using CSETWebCore.Business.Acet; -using CSETWebCore.Business.Maturity; using CSETWebCore.Business.Maturity.Configuration; -using CSETWebCore.Business.Question; using CSETWebCore.Business.Sal; -using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; using CSETWebCore.Helpers; using CSETWebCore.Interfaces.AdminTab; @@ -18,24 +14,16 @@ using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; using CSETWebCore.Model.Diagram; -using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; using CSETWebCore.Model.Reports; -using CSETWebCore.Model.Set; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Nelibur.ObjectMapper; using Snickler.EFCore; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Runtime.Intrinsics.Arm; -using System.Text.RegularExpressions; using System.Threading.Tasks; -using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports diff --git a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs index ba64e93442..a3da3ccb49 100644 --- a/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs +++ b/CSETWebApi/CSETWeb_Api/CSETWebCore.Business/Reports/ReportsData/ReportsUtils.cs @@ -4,38 +4,17 @@ // // //////////////////////////////// -using CSETWebCore.Business.Acet; -using CSETWebCore.Business.Maturity; -using CSETWebCore.Business.Maturity.Configuration; using CSETWebCore.Business.Question; -using CSETWebCore.Business.Sal; -using CSETWebCore.DataLayer.Manual; using CSETWebCore.DataLayer.Model; using CSETWebCore.Helpers; -using CSETWebCore.Interfaces.AdminTab; -using CSETWebCore.Interfaces.Helpers; -using CSETWebCore.Interfaces.Maturity; -using CSETWebCore.Interfaces.Question; using CSETWebCore.Interfaces.Reports; -using CSETWebCore.Model.Diagram; -using CSETWebCore.Model.Document; using CSETWebCore.Model.Maturity; using CSETWebCore.Model.Question; using CSETWebCore.Model.Reports; -using CSETWebCore.Model.Set; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Nelibur.ObjectMapper; -using Snickler.EFCore; using System; using System.Collections.Generic; -using System.ComponentModel; using System.Linq; -using System.Runtime.Intrinsics.Arm; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using static Lucene.Net.Util.Fst.Util; namespace CSETWebCore.Business.Reports