示例#1
0
    def error_check(self, report_data):
        """
        Check all input for errors. The called functions will throw exceptions
        themselves. We are not trying to catch them, but to trigger them before
        we try to commit everything to the DB. This should prevent inconsistent data
        in the DB.
        :param report_data:
        :return:
        """
        section_api = SectionApi(autocommit=False)
        question_api = QuestionApi(autocommit=False)
        risk_factor_api = RiskFactorApi()

        # Database check
        if self.db_check(report_data) is not True:
            raise Exception(_('An unexpected error occurred.'))

        # Check for attributes
        if 'sections' not in report_data:
            raise RequiredAttributeMissing(
                _e['attr_missing'].format('sections'))
        cleaned_report = self.parse_input_data(report_data)

        # Check for duplicates (two sections with the same title)
        duplicate_sections = []
        for section in report_data['sections']:
            if 'questions' not in section:
                raise RequiredAttributeMissing(
                    _e['attr_missing'].format('questions'))

            # Check for attributes
            cleaned_section = section_api.parse_input_data(section)
            # Duplicate check
            if section['title'] not in duplicate_sections:
                duplicate_sections.append(section['title'])
            else:
                raise DatabaseItemAlreadyExists(_e['item_already_in'].format(
                    'Section', section['title'], 'Report', report_data['id']))

            duplicate_questions = []
            for question in section['questions']:
                # Check for attributes
                cleaned_question = question_api.parse_input_data(question)
                # Check for duplicates
                if question['question'] not in duplicate_questions:
                    duplicate_questions.append(question['question'])
                else:
                    raise DatabaseItemAlreadyExists(
                        _e['item_already_in'].format('Question',
                                                     question['question'],
                                                     'Section', section['id']))
                # Check for answers
                # We must use the cleaned data, because 'answers' is not required,
                # and attempting to loop over None gets an error.
                for answer_id in cleaned_question['answers']:
                    answer = question_api.get_answer(answer_id)
                # Check for risk_factor
                risk_factor = risk_factor_api.read(
                    cleaned_question['risk_factor_id'])
        return True
示例#2
0
 def get_for_section_by_question_id(self, section_id, user_id,
                                    user_report_id):
     """
     Get all questionAnswers for a specific section (section_id) in a dict
     where the key is the question_id, for a specific user in a specific UserReport
     :param section_id:
     :param user_id:
     :param user_report_id:
     :return:
     """
     section_api = SectionApi()
     current_section = section_api.read(section_id)
     ordered_questions = {}
     for question in current_section.questions:
         if question.id in ordered_questions:
             raise DatabaseItemAlreadyExists(
                 _('Error: two questions with the same id in one section!'))
         # Get the QuestionAnswers object
         try:
             question_answer = self.get_answer_by_question_id(
                 question.id, user_id, user_report_id)
         except DatabaseItemDoesNotExist:
             continue
         ordered_questions[question.id] = question_answer
     return ordered_questions
示例#3
0
 def hook_add_total_score(output_data):
     if section_id is not None:
         new_output = output_data
         new_output['total_score'] = SectionApi().total_score(section_id)
     else:
         new_output = []
         for item in output_data:
             item['total_score'] = SectionApi().total_score(item['id'])
             new_output.append(item)
     return new_output
示例#4
0
 def test_create(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     assert s in scoremodel.db.session
     assert s.order_in_report == 0
     self.assertIsInstance(s, Section)
     self.assertRaises(DatabaseItemAlreadyExists,
                       SectionApi().create, {
                           'title': 'Test',
                           'report_id': r.id
                       })
示例#5
0
 def hook_add_multiplication_factor(output_data):
     if section_id is not None:
         new_output = output_data
         new_output['multiplication_factor'] = SectionApi(
         ).multiplication_factor(section_id)
     else:
         new_output = []
         for item in output_data:
             item['multiplication_factor'] = SectionApi(
             ).multiplication_factor(item['id'])
             new_output.append(item)
     return new_output
示例#6
0
 def test_update(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     s_u = SectionApi().update(s.id, {
         'title': 'Toto',
         'report_id': r.id,
         'order_in_report': 1
     })
     assert s_u == SectionApi().read(s.id)
     assert SectionApi().read(s.id).title == 'Toto'
     assert SectionApi().read(s.id).order_in_report == 1
     self.assertIsInstance(s_u, Section)
示例#7
0
    def store_chain(self, report_data, created_report):
        """
        For an already stored report (created_report), store all sections
        and attached questions in the DB. Will automatically distinguish between
        new sections/questions and updated sections/questions.
        :param report_data:
        :param created_report:
        :return:
        """
        section_api = SectionApi()
        question_api = QuestionApi()
        # Check for sections that were originally part of created_report, but are not anymore
        # We delete those.
        original_sections = created_report.sections
        new_sections = []
        for s in report_data['sections']:
            if 'id' in s:
                new_sections.append(s)
        #for original_section in original_sections:
        #    if original_section.id not in new_sections:
        #        section_api.delete(original_section.id)

        for section in report_data['sections']:
            section['report_id'] = created_report.id
            if 'id' in section and section['id'] > 0:
                # An update
                created_section = section_api.update(section['id'], section)
            else:
                # A new creation
                created_section = section_api.create(section)
            original_questions = created_section.questions
            new_questions = []
            for q in section['questions']:
                if 'id' in q:
                    new_questions.append(q)
            #for original_question in original_questions:
            #    if original_question.id not in new_questions:
            #        question_api.delete(original_question.id)
            for question in section['questions']:
                question['section_id'] = created_section.id
                if 'id' in question and question['id'] > 0:
                    # An update
                    created_question = question_api.update(
                        question['id'], question)
                else:
                    # A new creation
                    created_question = question_api.create(question)
        return created_report
示例#8
0
 def test_delete(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     q = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id})
     assert QuestionApi().delete(q.id) is True
     assert q not in scoremodel.db.session
示例#9
0
 def hook_add_multiplication_factor(output_data):
     if type(output_data) is not dict:
         return output_data
     question = QuestionApi().read(question_id)
     output_data['multiplication_factor'] = SectionApi(
     ).multiplication_factor(question.section_id)
     return output_data
示例#10
0
 def benchmarks_by_section(self, user_report_id):
     """
     Get all benchmark questions (grouped per report) per section.
     :param user_report_id:
     :return:
     """
     bm_by_section = {}
     benchmark_report_api = BenchmarkReportApi()
     existing_user_report = self.read(user_report_id)
     for benchmark_report in existing_user_report.template.benchmark_reports:
         benchmark_questions_by_section = benchmark_report_api.questions_by_section(benchmark_report.id)
         for section_id, benchmarks in benchmark_questions_by_section.items():
             section_score = 0
             multiplication_factor = SectionApi().multiplication_factor(section_id)
             for benchmark in benchmarks:
                 section_score += benchmark.score * multiplication_factor
             if section_id in bm_by_section:
                 if benchmark_report.id in bm_by_section[section_id]:
                     raise Exception(_('Multiple values for the same benchmark_report in the same section.'))
                 else:
                     bm_by_section[section_id][benchmark_report.id] = {
                         'title': benchmark_report.title,
                         'section_score': section_score,
                         'benchmarks': {b.question_id: b for b in benchmark_questions_by_section[section_id]}
                     }
             else:
                 bm_by_section[section_id] = {
                     benchmark_report.id: {
                         'title': benchmark_report.title,
                         'section_score': section_score,
                         'benchmarks': {b.question_id: b for b in benchmark_questions_by_section[section_id]}
                     }
                 }
     return bm_by_section
示例#11
0
def v_user_report_section(user_id, user_report_id, section_id):
    section_api = SectionApi()
    if current_user.id != user_id:
        flash(_('You can only view your own reports.'))
        abort(403)
        return
    try:
        user_report = user_report_api.read(user_report_id)
    except DatabaseItemDoesNotExist as e:
        abort(404)
        return
    except Exception as e:
        flash(_('An unexpected error occurred.'))
        return redirect(url_for('site.v_index'))

    # Check whether current section is in this user_report
    if section_id not in [
            section.id for section in user_report.template.sections
    ]:
        abort(404)
        return

    current_section = section_api.read(section_id)

    # Get all question_answers for this report and order them by question_id, so we can compare
    # question.answer.answer_id to question_answers['question_id'].answer_id
    question_answers = {}
    for question_answer in user_report.question_answers:
        question_answers[question_answer.question_id] = question_answer

    benchmarks_by_section = user_report_api.benchmarks_by_section(
        user_report_id)

    # Create a color-range for the risk_factors
    risk_factors = [r.risk_factor for r in RiskFactorApi().list()]
    colored_risk_factors = Color().range(risk_factors)

    return render_template('public/section.html',
                           title=current_section.title,
                           section=current_section,
                           user_report_id=user_report_id,
                           question_answers=question_answers,
                           next_section=current_section.next_in_report,
                           previous_section=current_section.previous_in_report,
                           benchmarks_by_section=benchmarks_by_section,
                           colored_risk_factors=colored_risk_factors)
示例#12
0
def v_user_report_summary(user_id, user_report_id):
    if current_user.id != user_id:
        flash(_('You can only view your own reports.'))
        abort(403)
    user_report = user_report_api.read(user_report_id)

    question_answers = {}
    all_scores = {}

    for section in user_report.template.sections:
        all_scores[section.id] = 0

    for question_answer in user_report.question_answers:
        question_answers[question_answer.question_id] = question_answer
        multiplication_factor = SectionApi().multiplication_factor(
            question_answer.question_template.section_id)
        all_scores[question_answer.question_template.section.id] += question_answer.score * \
                                                                    multiplication_factor

    highest_unanswered = []

    for question in ReportApi().questions_by_combined_weight(
            user_report.template.id):
        if question['question_id'] not in question_answers or question_answers[question['question_id']].score < \
                question['max_score']:
            try:
                highest_unanswered.append(QuestionApi().read(
                    question['question_id']))
            except DatabaseItemDoesNotExist:
                pass

    if len(highest_unanswered) >= 5:
        visible_unanswered = highest_unanswered[:5]
    else:
        visible_unanswered = highest_unanswered

    benchmarks_by_question = {}
    for bm_r in user_report.template.benchmark_reports:
        for bm in bm_r.benchmarks:
            if bm.question_id in benchmarks_by_question:
                benchmarks_by_question[bm.question_id].append(bm)
            else:
                benchmarks_by_question[bm.question_id] = [bm]

    # Create a color-range for the risk_factors
    risk_factors = [r.risk_factor for r in RiskFactorApi().list()]
    colored_risk_factors = Color().range(risk_factors)

    return render_template(
        'public/summary.html',
        report_template=user_report.template,
        user_report=user_report,
        user_report_creation_time='{:%Y-%m-%d %H:%M:%S}'.format(
            user_report.creation_time),
        highest_unanswered=visible_unanswered,
        benchmarks_by_question=benchmarks_by_question,
        question_answers_by_id=question_answers,
        colored_risk_factors=colored_risk_factors)
示例#13
0
 def test_update(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     q = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id})
     q_d = QuestionApi().update(q.id, {'question': 'Foo', 'weight': 1, 'section_id': s.id})
     assert q_d == QuestionApi().read(q.id)
     assert QuestionApi().read(q.id).question == 'Foo'
     self.assertIsInstance(q_d, Question)
示例#14
0
 def test_create(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     q = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id})
     assert q in scoremodel.db.session
     # This only works in a context manager, and not with self.assertRaises() - I have no idea why.
     with self.assertRaises(DatabaseItemAlreadyExists):
         x = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id})
     self.assertIsInstance(q, Question)
示例#15
0
 def test_complex(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     ri = RiskFactorApi().create({'risk_factor': 'Test', 'lang_id': en.id})
     a = AnswerApi().create({'answer': 'Test', 'lang_id': en.id})
     q = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id, 'answers': [a.id],
                               'risk_factor_id': ri.id})
     assert q in scoremodel.db.session
     self.assertIsInstance(q, Question)
示例#16
0
 def db_check(self, report_data):
     """
     For a report, check that reports, sections and questions do not already exist
     in the database when they are new.
     :param report_data:
     :return:
     """
     section_api = SectionApi(autocommit=False)
     question_api = QuestionApi(autocommit=False)
     if 'sections' not in report_data:
         raise RequiredAttributeMissing(
             _e['attr_missing'].format('sections'))
     if 'id' in report_data and report_data['id'] > 0:
         # Check the DB
         for section in report_data['sections']:
             # If there is no title, this will be caught by the other error checking routines
             if 'title' in section:
                 if 'id' not in section or section['id'] < 0:
                     if section_api.db_exists(section['title'],
                                              report_data['id']):
                         raise DatabaseItemAlreadyExists(
                             _e['item_already_in'].format(
                                 'Section', section['title'], 'Report',
                                 report_data['id']))
             if 'id' in section and section['id'] > 0:
                 # No sense in checking for questions in a section that doesn't exist
                 if 'questions' not in section:
                     raise RequiredAttributeMissing(
                         _e['attr_missing'].format('questions'))
                 for question in section['questions']:
                     if 'question' in question:
                         if 'id' not in question or question['id'] < 0:
                             if question_api.db_exists(
                                     question['question'], section['id']):
                                 raise DatabaseItemAlreadyExists(
                                     _e['item_already_in'].format(
                                         'Question', question['question'],
                                         'Section', section['id']))
     return True
示例#17
0
 def test_complex(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({
         'title': 'Test',
         'report_id': r.id,
         'order_in_report': 2,
         'weight': 5
     })
     assert s in scoremodel.db.session
     assert s.order_in_report == 2
     assert s.weight == 5
     self.assertIsInstance(s, Section)
示例#18
0
def v_user_report_check(user_id, user_report_id):
    if current_user.id != user_id:
        flash(_('You can only view your own reports.'))
        abort(403)
    user_report = user_report_api.read(user_report_id)

    # Get all question_answers for this report and order them by question_id, so we can compare
    # question.answer.answer_id to question_answers['question_id'].answer_id

    question_answers = {}
    all_scores = {}
    highest_answers = {}

    for section in user_report.template.sections:
        all_scores[section.id] = 0

    for question_answer in user_report.question_answers:
        question = question_answer.question_template
        question_answers[question.id] = question_answer
        multiplication_factor = SectionApi().multiplication_factor(
            question.section_id)
        all_scores[question.
                   section_id] += question_answer.score * multiplication_factor
        sorted_answers = sorted(question.answers,
                                key=lambda a: a.value,
                                reverse=True)
        if len(sorted_answers) > 0:
            highest_answers[question.id] = sorted_answers[0].value
        else:
            highest_answers[question.id] = 0

    benchmarks_by_section = user_report_api.benchmarks_by_section(
        user_report_id)

    # Create a color-range for the risk_factors
    risk_factors = [r.risk_factor for r in RiskFactorApi().list()]
    colored_risk_factors = Color().range(risk_factors)

    return render_template(
        'public/report.html',
        report_template=user_report.template,
        user_report=user_report,
        user_report_creation_time='{:%Y-%m-%d %H:%M:%S}'.format(
            user_report.creation_time),
        question_answers=question_answers,
        all_scores=all_scores,
        benchmarks_by_section=benchmarks_by_section,
        highest_answers=highest_answers,
        colored_risk_factors=colored_risk_factors)
示例#19
0
 def hook_add_multiplication_factor(output_data):
     if type(output_data) is not dict:
         return output_data
     new_question_answers_by_section = []
     for section in output_data['question_answers_by_section']:
         question_answers = []
         for qa in section['question_answers']:
             qa['multiplication_factor'] = SectionApi(
             ).multiplication_factor(section['section_id'])
             question_answers.append(qa)
         section['question_answers'] = question_answers
         new_question_answers_by_section.append(section)
     output_data[
         'question_answers_by_section'] = new_question_answers_by_section
     return output_data
示例#20
0
 def hook_add_by_section(output_data):
     for section_id, benchmarks in BenchmarkReportApi(
     ).questions_by_section(benchmark_report_id).items():
         section_benchmarks = []
         for b in benchmarks:
             b_out = b.output_obj()
             b_out['multiplication_factor'] = SectionApi(
             ).multiplication_factor(b.question.section_id)
             section_benchmarks.append(b_out)
         output_data['benchmarks_by_section'].append({
             'section_id':
             section_id,
             'benchmarks':
             section_benchmarks
         })
     return output_data
示例#21
0
 def test_read(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     assert s == SectionApi().read(s.id)
示例#22
0
 def test_delete(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     assert SectionApi().delete(s.id) is True
     assert s not in scoremodel.db.session
示例#23
0
 def test_read(self):
     en = LangApi().by_lang('en')
     r = ReportApi().create({'title': 'Test', 'lang_id': en.id})
     s = SectionApi().create({'title': 'Test', 'report_id': r.id})
     q = QuestionApi().create({'question': 'Test', 'weight': 1, 'section_id': s.id})
     assert q == QuestionApi().read(q.id)