/// <summary> /// Recursive method that builds subgroupings for the specified group. /// It also attaches any questions pertinent to this group. /// </summary> private void BuildSubGroupings(MaturityGrouping g, int?parentID, List <MATURITY_GROUPINGS> allGroupings, List <MATURITY_QUESTIONS> questions, List <FullAnswer> answers) { var mySubgroups = allGroupings.Where(x => x.Parent_Id == parentID).OrderBy(x => x.Sequence).ToList(); if (mySubgroups.Count == 0) { return; } foreach (var sg in mySubgroups) { var newGrouping = new MaturityGrouping() { GroupingID = sg.Grouping_Id, GroupingType = sg.Type.Grouping_Type_Name, Title = sg.Title, Description = sg.Description, Abbreviation = sg.Abbreviation }; g.SubGroupings.Add(newGrouping); // are there any questions that belong to this grouping? var myQuestions = questions.Where(x => x.Grouping_Id == newGrouping.GroupingID).ToList(); var parentQuestionIDs = myQuestions.Select(x => x.Parent_Question_Id).Distinct().ToList(); foreach (var myQ in myQuestions) { FullAnswer answer = answers.Where(x => x.a.Question_Or_Requirement_Id == myQ.Mat_Question_Id).FirstOrDefault(); var qa = new QuestionAnswer() { DisplayNumber = myQ.Question_Title, QuestionId = myQ.Mat_Question_Id, ParentQuestionId = myQ.Parent_Question_Id, Sequence = myQ.Sequence, QuestionType = "Maturity", QuestionText = myQ.Question_Text.Replace("\r\n", "<br/>").Replace("\n", "<br/>").Replace("\r", "<br/>"), Answer = answer?.a.Answer_Text, AltAnswerText = answer?.a.Alternate_Justification, Comment = answer?.a.Comment, Feedback = answer?.a.Feedback, MarkForReview = answer?.a.Mark_For_Review ?? false, Reviewed = answer?.a.Reviewed ?? false, Is_Maturity = true, MaturityLevel = myQ.Maturity_LevelNavigation.Level, MaturityLevelName = myQ.Maturity_LevelNavigation.Level_Name, IsParentQuestion = parentQuestionIDs.Contains(myQ.Mat_Question_Id), SetName = string.Empty }; if (answer != null) { TinyMapper.Bind <VIEW_QUESTIONS_STATUS, QuestionAnswer>(); TinyMapper.Map(answer.b, qa); } newGrouping.Questions.Add(qa); } newGrouping.Questions.Sort((a, b) => a.Sequence.CompareTo(b.Sequence)); // Recurse down to build subgroupings BuildSubGroupings(newGrouping, newGrouping.GroupingID, allGroupings, questions, answers); } }
/// <summary> /// /// </summary> /// <param name="assessmentId"></param> public object GetMaturityQuestions(int assessmentId) { // Populate response var response = new QuestionResponse { Domains = new List <Domain>() }; using (var db = new CSET_Context()) { var myModel = db.AVAILABLE_MATURITY_MODELS .Include(x => x.model_) .Where(x => x.Assessment_Id == assessmentId).FirstOrDefault(); if (myModel == null) { return(response); } // see if any answer options should not be in the list var suppressedAnswerOptions = myModel.model_.Answer_Options_Suppressed; if (!string.IsNullOrEmpty(suppressedAnswerOptions)) { var a = suppressedAnswerOptions.Split(','); foreach (string suppress in a) { response.AnswerOptions.Remove(suppress); } } // The maturity target level is stored similar to a SAL level int targetLevel = 0; var myLevel = db.ASSESSMENT_SELECTED_LEVELS.Where(x => x.Assessment_Id == assessmentId && x.Level_Name == "Maturity_Level").FirstOrDefault(); if (myLevel != null) { targetLevel = int.Parse(myLevel.Standard_Specific_Sal_Level); } // get the level display names // (for now assume that the assessment uses a single model) var levelNames = new List <MaturityLevel>(); foreach (var l in db.MATURITY_LEVELS.Where(x => x.Maturity_Model_Id == myModel.model_id) .OrderBy(y => y.Level).ToList()) { levelNames.Add(new MaturityLevel() { Level = l.Level, Label = l.Level_Name, Applicable = l.Level <= targetLevel }); } // Get all maturity questions for the model regardless of level // The user can choose to see questions above the target level via filtering. var questions = db.MATURITY_QUESTIONS.Where(q => myModel.model_id == q.Maturity_Model_Id).ToList(); // Get all MATURITY answers for the assessment var answers = from a in db.ANSWER.Where(x => x.Assessment_Id == assessmentId && x.Is_Maturity) from b in db.VIEW_QUESTIONS_STATUS.Where(x => x.Answer_Id == a.Answer_Id).DefaultIfEmpty() select new FullAnswer() { a = a, b = b }; // CMMC has 17 domains, which correspond to Categories in the // MATURITY_QUESTIONS table. // TODO: Eventually they should probably be defined in a new generic // MATURITY_DOMAINS table. var domains = questions.Select(x => x.Category).Distinct().ToList(); // build a container for each domain foreach (var d in domains) { response.Domains.Add(new Domain() { DisplayText = d, DomainText = d, Levels = levelNames }); } foreach (var dbR in questions) { // Make sure there are no leading or trailing spaces - it will affect the tree structure that is built dbR.Category = dbR.Category ?? dbR.Category.Trim(); dbR.Sub_Category = dbR.Sub_Category ?? dbR.Sub_Category.Trim(); // If the Standard_Sub_Category is null (like CSC_V6), default it to the Standard_Category if (dbR.Sub_Category == null) { dbR.Sub_Category = dbR.Category; } var json = JsonConvert.SerializeObject(response); // drop into the domain var targetDomain = response.Domains.Where(cc => cc.DomainText == dbR.Category).FirstOrDefault(); if (targetDomain != null) { // find or create a Category var targetCat = targetDomain.Categories.Where(c => c.GroupHeadingText == dbR.Category).FirstOrDefault(); if (targetCat == null) { targetCat = new QuestionGroup() { GroupHeadingText = dbR.Category }; targetDomain.Categories.Add(targetCat); } // find or create a Subcategory var targetSubcat = targetCat.SubCategories.Where(sc => sc.SubCategoryHeadingText == dbR.Sub_Category).FirstOrDefault(); if (targetSubcat == null) { targetSubcat = new QuestionSubCategory() { SubCategoryId = 0, SubCategoryHeadingText = dbR.Sub_Category, // GroupHeadingId = g.GroupHeadingId }; targetCat.SubCategories.Add(targetSubcat); } FullAnswer answer = answers.Where(x => x.a.Question_Or_Requirement_Id == dbR.Mat_Question_Id).FirstOrDefault(); var qa = new QuestionAnswer() { DisplayNumber = dbR.Question_Title, QuestionId = dbR.Mat_Question_Id, QuestionText = dbR.Question_Text.Replace("\r\n", "<br/>").Replace("\n", "<br/>").Replace("\r", "<br/>"), Answer = answer?.a.Answer_Text, AltAnswerText = answer?.a.Alternate_Justification, Comment = answer?.a.Comment, Feedback = answer?.a.Feedback, MarkForReview = answer?.a.Mark_For_Review ?? false, Reviewed = answer?.a.Reviewed ?? false, MaturityLevel = dbR.Maturity_Level, SetName = string.Empty, Is_Maturity = answer?.a.Is_Maturity ?? true, Is_Component = answer?.a.Is_Component ?? false, Is_Requirement = answer?.a.Is_Requirement ?? false }; if (answer != null) { TinyMapper.Bind <VIEW_QUESTIONS_STATUS, QuestionAnswer>(); TinyMapper.Map(answer.b, qa); } qa.ParmSubs = null; targetSubcat.Questions.Add(qa); } } return(response); } }