def _setup_questionnaires(self): """Locates questionnaires and verifies that they have the appropriate questions in them.""" questionnaire_dao = QuestionnaireDao() code_dao = CodeDao() question_code_to_questionnaire_id = {} self._questionnaire_to_questions = collections.defaultdict(list) self._question_code_to_answer_codes = {} # Populate maps of questionnaire ID/version to [(question_code, link ID)] and # question code to answer codes. for concept in _QUESTIONNAIRE_CONCEPTS: code = code_dao.get_code(PPI_SYSTEM, concept) if code is None: raise BadRequest( 'Code missing: %s; import data and clear cache.' % concept) questionnaire = questionnaire_dao.get_latest_questionnaire_with_concept( code.codeId) if questionnaire is None: raise BadRequest( 'Questionnaire for code %s missing; import data.' % concept) questionnaire_id_and_version = (questionnaire.questionnaireId, questionnaire.version) if concept == CONSENT_FOR_STUDY_ENROLLMENT_MODULE: self._consent_questionnaire_id_and_version = questionnaire_id_and_version elif concept == THE_BASICS_PPI_MODULE: self._the_basics_questionnaire_id_and_version = questionnaire_id_and_version questions = self._questionnaire_to_questions[ questionnaire_id_and_version] if questions: # We already handled this questionnaire. continue for question in questionnaire.questions: question_code = code_dao.get(question.codeId) if (question_code.value in _QUESTION_CODES) or (question_code.value in self._answer_specs): question_code_to_questionnaire_id[ question_code.value] = questionnaire.questionnaireId questions.append((question_code.value, question.linkId)) if question_code.value in _QUESTION_CODES: answer_codes = self._get_answer_codes(question_code) all_codes = (answer_codes + _CONSTANT_CODES ) if answer_codes else _CONSTANT_CODES self._question_code_to_answer_codes[ question_code.value] = all_codes # Log warnings for any question codes not found in the questionnaires. for code_value in _QUESTION_CODES + self._answer_specs.keys(): questionnaire_id = question_code_to_questionnaire_id.get( code_value) if not questionnaire_id: logging.warning( 'Question for code %s missing; import questionnaires', code_value)
class QuestionnaireDaoTest(SqlTestBase): def setUp(self): super(QuestionnaireDaoTest, self).setUp(with_data=False) self.dao = QuestionnaireDao() self.questionnaire_history_dao = QuestionnaireHistoryDao() self.questionnaire_concept_dao = QuestionnaireConceptDao() self.questionnaire_question_dao = QuestionnaireQuestionDao() self.code_dao = CodeDao() self.CODE_1 = Code(codeId=1, system='a', value='b', display=u'c', topic=u'd', codeType=CodeType.MODULE, mapped=True) self.CODE_2 = Code(codeId=2, system='a', value='x', display=u'y', codeType=CodeType.MODULE, mapped=False) self.CODE_3 = Code(codeId=3, system='a', value='z', display=u'y', codeType=CodeType.MODULE, mapped=False) self.CODE_4 = Code(codeId=4, system='a', value='c', codeType=CodeType.QUESTION, mapped=True, parentId=1) self.CODE_5 = Code(codeId=5, system='a', value='d', codeType=CodeType.QUESTION, mapped=True, parentId=2) self.CODE_6 = Code(codeId=6, system='a', value='e', codeType=CodeType.QUESTION, mapped=True, parentId=2) self.CONCEPT_1 = QuestionnaireConcept(codeId=1) self.CONCEPT_2 = QuestionnaireConcept(codeId=2) self.QUESTION_1 = QuestionnaireQuestion(linkId='a', codeId=4, repeats=False) self.QUESTION_2 = QuestionnaireQuestion(linkId='d', codeId=5, repeats=True) self.insert_codes() def insert_codes(self): self.code_dao.insert(self.CODE_1) self.code_dao.insert(self.CODE_2) self.code_dao.insert(self.CODE_3) self.code_dao.insert(self.CODE_4) self.code_dao.insert(self.CODE_5) self.code_dao.insert(self.CODE_6) def test_get_before_insert(self): self.assertIsNone(self.dao.get(1)) self.assertIsNone(self.dao.get_with_children(1)) self.assertIsNone( self.dao.get_latest_questionnaire_with_concept(self.CODE_1.codeId)) self.assertIsNone(self.questionnaire_history_dao.get([1, 1])) self.assertIsNone( self.questionnaire_history_dao.get_with_children([1, 1])) self.assertIsNone(self.questionnaire_concept_dao.get(1)) self.assertIsNone(self.questionnaire_question_dao.get(1)) def check_history(self): expected_history = QuestionnaireHistory(questionnaireId=1, version=1, created=TIME, lastModified=TIME, resource=RESOURCE_1_WITH_ID) questionnaire_history = self.questionnaire_history_dao.get([1, 1]) self.assertEquals(expected_history.asdict(), questionnaire_history.asdict()) questionnaire_history = self.questionnaire_history_dao.get_with_children( [1, 1]) expected_history.concepts.append(EXPECTED_CONCEPT_1) expected_history.concepts.append(EXPECTED_CONCEPT_2) expected_history.questions.append(EXPECTED_QUESTION_1) expected_history.questions.append(EXPECTED_QUESTION_2) self.assertEquals(EXPECTED_CONCEPT_1.asdict(), self.questionnaire_concept_dao.get(1).asdict()) self.assertEquals(EXPECTED_CONCEPT_2.asdict(), self.questionnaire_concept_dao.get(2).asdict()) self.assertEquals(EXPECTED_QUESTION_1.asdict(), self.questionnaire_question_dao.get(1).asdict()) self.assertEquals(EXPECTED_QUESTION_2.asdict(), self.questionnaire_question_dao.get(2).asdict()) def test_insert(self): q = Questionnaire(resource=RESOURCE_1) q.concepts.append(self.CONCEPT_1) q.concepts.append(self.CONCEPT_2) q.questions.append(self.QUESTION_1) q.questions.append(self.QUESTION_2) with FakeClock(TIME): self.dao.insert(q) # Creating a questionnaire creates a history entry with children self.check_history() expected_questionnaire = Questionnaire(questionnaireId=1, version=1, created=TIME, lastModified=TIME, resource=RESOURCE_1_WITH_ID) questionnaire = self.dao.get(1) self.assertEquals(expected_questionnaire.asdict(), questionnaire.asdict()) expected_questionnaire.concepts.append(EXPECTED_CONCEPT_1) expected_questionnaire.concepts.append(EXPECTED_CONCEPT_2) expected_questionnaire.questions.append(EXPECTED_QUESTION_1) expected_questionnaire.questions.append(EXPECTED_QUESTION_2) questionnaire = self.dao.get_with_children(1) self.assertEquals( sort_lists(expected_questionnaire.asdict_with_children()), sort_lists(questionnaire.asdict_with_children())) self.assertEquals( questionnaire.asdict(), self.dao.get_latest_questionnaire_with_concept( self.CODE_1.codeId).asdict()) def test_insert_duplicate(self): q = Questionnaire(questionnaireId=1, resource=RESOURCE_1) self.dao.insert(q) try: self.dao.insert(q) self.fail("IntegrityError expected") except IntegrityError: pass def test_update_right_expected_version(self): q = Questionnaire(resource=RESOURCE_1) with FakeClock(TIME): self.dao.insert(q) q = Questionnaire(questionnaireId=1, version=1, resource=RESOURCE_2) with FakeClock(TIME_2): self.dao.update(q) expected_questionnaire = Questionnaire(questionnaireId=1, version=2, created=TIME, lastModified=TIME_2, resource=RESOURCE_2_WITH_ID) questionnaire = self.dao.get(1) self.assertEquals(expected_questionnaire.asdict(), questionnaire.asdict()) def test_update_wrong_expected_version(self): q = Questionnaire(resource=RESOURCE_1) with FakeClock(TIME): self.dao.insert(q) q = Questionnaire(questionnaireId=1, version=2, resource=RESOURCE_2) with FakeClock(TIME_2): try: self.dao.update(q) self.fail("PreconditionFailed expected") except PreconditionFailed: pass def test_update_not_exists(self): q = Questionnaire(questionnaireId=1, resource=RESOURCE_1) try: self.dao.update(q) self.fail("NotFound expected") except NotFound: pass def test_insert_multiple_questionnaires_same_concept(self): q = Questionnaire(resource=RESOURCE_1) q.concepts.append(self.CONCEPT_1) q.concepts.append(self.CONCEPT_2) with FakeClock(TIME): self.dao.insert(q) q2 = Questionnaire(resource=RESOURCE_2) q2.concepts.append(self.CONCEPT_1) with FakeClock(TIME_2): self.dao.insert(q2) self.assertEquals( 2, self.dao.get_latest_questionnaire_with_concept( self.CODE_1.codeId).questionnaireId) self.assertEquals( 1, self.dao.get_latest_questionnaire_with_concept( self.CODE_2.codeId).questionnaireId)