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)
Exemple #2
0
    def _update_participant_summary(self, session, questionnaire_response,
                                    code_ids, questions, questionnaire_history,
                                    resource_json):
        """Updates the participant summary based on questions answered and modules completed
    in the questionnaire response.

    If no participant summary exists already, only a response to the study enrollment consent
    questionnaire can be submitted, and it must include first and last name and e-mail address.
    """

        # Block on other threads modifying the participant or participant summary.
        participant = ParticipantDao().get_for_update(
            session, questionnaire_response.participantId)

        if participant is None:
            raise BadRequest('Participant with ID %d is not found.' %
                             questionnaire_response.participantId)

        participant_summary = participant.participantSummary

        code_ids.extend(
            [concept.codeId for concept in questionnaire_history.concepts])

        code_dao = CodeDao()

        something_changed = False
        # If no participant summary exists, make sure this is the study enrollment consent.
        if not participant_summary:
            consent_code = code_dao.get_code(
                PPI_SYSTEM, CONSENT_FOR_STUDY_ENROLLMENT_MODULE)
            if not consent_code:
                raise BadRequest(
                    'No study enrollment consent code found; import codebook.')
            if not consent_code.codeId in code_ids:
                raise BadRequest(
                    "Can't submit order for participant %s without consent" %
                    questionnaire_response.participantId)
            raise_if_withdrawn(participant)
            participant_summary = ParticipantDao.create_summary_for_participant(
                participant)
            something_changed = True
        else:
            raise_if_withdrawn(participant_summary)

        # Fetch the codes for all questions and concepts
        codes = code_dao.get_with_ids(code_ids)

        code_map = {
            code.codeId: code
            for code in codes if code.system == PPI_SYSTEM
        }
        question_map = {
            question.questionnaireQuestionId: question
            for question in questions
        }
        race_code_ids = []
        ehr_consent = False
        dvehr_consent = QuestionnaireStatus.SUBMITTED_NO_CONSENT
        # Set summary fields for answers that have questions with codes found in QUESTION_CODE_TO_FIELD
        for answer in questionnaire_response.answers:
            question = question_map.get(answer.questionId)
            if question:
                code = code_map.get(question.codeId)
                if code:
                    summary_field = QUESTION_CODE_TO_FIELD.get(code.value)
                    if summary_field:
                        if something_changed:
                            self._update_field(participant_summary,
                                               summary_field[0],
                                               summary_field[1], answer)
                        else:
                            something_changed = self._update_field(
                                participant_summary, summary_field[0],
                                summary_field[1], answer)
                    elif code.value == RACE_QUESTION_CODE:
                        race_code_ids.append(answer.valueCodeId)

                    elif code.value == DVEHR_SHARING_QUESTION_CODE:
                        code = code_dao.get(answer.valueCodeId)
                        if code and code.value == DVEHRSHARING_CONSENT_CODE_YES:
                            dvehr_consent = QuestionnaireStatus.SUBMITTED
                        elif code and code.value == DVEHRSHARING_CONSENT_CODE_NOT_SURE:
                            dvehr_consent = QuestionnaireStatus.SUBMITTED_NOT_SURE
                    elif code.value == EHR_CONSENT_QUESTION_CODE:
                        code = code_dao.get(answer.valueCodeId)
                        if code and code.value == CONSENT_PERMISSION_YES_CODE:
                            ehr_consent = True
                    elif code.value == CABOR_SIGNATURE_QUESTION_CODE:
                        if answer.valueUri or answer.valueString:
                            # TODO: validate the URI? [DA-326]
                            if not participant_summary.consentForCABoR:
                                participant_summary.consentForCABoR = True
                                participant_summary.consentForCABoRTime = questionnaire_response.created
                                something_changed = True

        # If race was provided in the response in one or more answers, set the new value.
        if race_code_ids:
            race_codes = [code_dao.get(code_id) for code_id in race_code_ids]
            race = get_race(race_codes)
            if race != participant_summary.race:
                participant_summary.race = race
                something_changed = True

        # Set summary fields to SUBMITTED for questionnaire concepts that are found in
        # QUESTIONNAIRE_MODULE_CODE_TO_FIELD
        module_changed = False
        for concept in questionnaire_history.concepts:
            code = code_map.get(concept.codeId)
            if code:
                summary_field = QUESTIONNAIRE_MODULE_CODE_TO_FIELD.get(
                    code.value)
                if summary_field:
                    new_status = QuestionnaireStatus.SUBMITTED
                    if code.value == CONSENT_FOR_ELECTRONIC_HEALTH_RECORDS_MODULE and not ehr_consent:
                        new_status = QuestionnaireStatus.SUBMITTED_NO_CONSENT
                    elif code.value == CONSENT_FOR_DVEHR_MODULE:
                        new_status = dvehr_consent
                    elif code.value == CONSENT_FOR_STUDY_ENROLLMENT_MODULE:
                        # set language of consent to participant summary
                        for extension in resource_json.get('extension', []):
                            if extension.get('url') == _LANGUAGE_EXTENSION and \
                              extension.get('valueCode') in LANGUAGE_OF_CONSENT:
                                if participant_summary.primaryLanguage != extension.get(
                                        'valueCode'):
                                    participant_summary.primaryLanguage = extension.get(
                                        'valueCode')
                                    something_changed = True
                                break
                            elif extension.get('url') == _LANGUAGE_EXTENSION and \
                              extension.get('valueCode') not in LANGUAGE_OF_CONSENT:
                                logging.warn(
                                    'consent language %s not recognized.' %
                                    extension.get('valueCode'))
                    if getattr(participant_summary,
                               summary_field) != new_status:
                        setattr(participant_summary, summary_field, new_status)
                        setattr(participant_summary, summary_field + 'Time',
                                questionnaire_response.created)
                        something_changed = True
                        module_changed = True
        if module_changed:
            participant_summary.numCompletedBaselinePPIModules = \
                count_completed_baseline_ppi_modules(participant_summary)
            participant_summary.numCompletedPPIModules = \
                count_completed_ppi_modules(participant_summary)

        if something_changed:
            first_last = (participant_summary.firstName,
                          participant_summary.lastName)
            email_phone = (participant_summary.email,
                           participant_summary.loginPhoneNumber)
            if not all(first_last):
                raise BadRequest(
                    'First name (%s), and last name (%s) required for consenting.'
                    % tuple([
                        'present' if part else 'missing' for part in first_last
                    ]))
            if not any(email_phone):
                raise BadRequest(
                    'Email address (%s), or phone number (%s) required for consenting.'
                    % tuple([
                        'present' if part else 'missing'
                        for part in email_phone
                    ]))

            ParticipantSummaryDao().update_enrollment_status(
                participant_summary)
            participant_summary.lastModified = clock.CLOCK.now()
            session.merge(participant_summary)

            # switch account to test account if the phone number is start with 444
            # this is a requirement from PTSC
            if participant_summary.loginPhoneNumber is not None and \
              participant_summary.loginPhoneNumber.startswith(TEST_LOGIN_PHONE_NUMBER_PREFIX):
                ParticipantDao().switch_to_test_account(
                    session, participant_summary.participantId)
  def _update_participant_summary(
      self, session, questionnaire_response, code_ids, questions, questionnaire_history):
    """Updates the participant summary based on questions answered and modules completed
    in the questionnaire response.

    If no participant summary exists already, only a response to the study enrollment consent
    questionnaire can be submitted, and it must include first and last name and e-mail address.
    """
    # Block on other threads modifying the participant or participant summary.
    participant = ParticipantDao().get_for_update(session, questionnaire_response.participantId)

    if participant is None:
      raise BadRequest('Participant with ID %d is not found.' %
                        questionnaire_response.participantId)

    participant_summary = participant.participantSummary

    code_ids.extend([concept.codeId for concept in questionnaire_history.concepts])

    code_dao = CodeDao()

    something_changed = False
    # If no participant summary exists, make sure this is the study enrollment consent.
    if not participant_summary:
      consent_code = code_dao.get_code(PPI_SYSTEM, CONSENT_FOR_STUDY_ENROLLMENT_MODULE)
      if not consent_code:
        raise BadRequest('No study enrollment consent code found; import codebook.')
      if not consent_code.codeId in code_ids:
        raise BadRequest("Can't submit order for participant %s without consent" %
                         questionnaire_response.participantId)
      raise_if_withdrawn(participant)
      participant_summary = ParticipantDao.create_summary_for_participant(participant)
      something_changed = True
    else:
      raise_if_withdrawn(participant_summary)

    # Fetch the codes for all questions and concepts
    codes = code_dao.get_with_ids(code_ids)

    code_map = {code.codeId: code for code in codes if code.system == PPI_SYSTEM}
    question_map = {question.questionnaireQuestionId: question for question in questions}
    race_code_ids = []
    ehr_consent = False
    # Set summary fields for answers that have questions with codes found in QUESTION_CODE_TO_FIELD
    for answer in questionnaire_response.answers:
      question = question_map.get(answer.questionId)
      if question:
        code = code_map.get(question.codeId)
        if code:
          summary_field = QUESTION_CODE_TO_FIELD.get(code.value)
          if summary_field:
            something_changed = self._update_field(participant_summary, summary_field[0],
                                                   summary_field[1], answer)
          elif code.value == RACE_QUESTION_CODE:
            race_code_ids.append(answer.valueCodeId)
          elif code.value == EHR_CONSENT_QUESTION_CODE:
            code = code_dao.get(answer.valueCodeId)
            if code and code.value == CONSENT_PERMISSION_YES_CODE:
              ehr_consent = True
          elif code.value == CABOR_SIGNATURE_QUESTION_CODE:
            if answer.valueUri or answer.valueString:
              # TODO: validate the URI? [DA-326]
              if not participant_summary.consentForCABoR:
                participant_summary.consentForCABoR = True
                participant_summary.consentForCABoRTime = questionnaire_response.created
                something_changed = True

    # If race was provided in the response in one or more answers, set the new value.
    if race_code_ids:
      race_codes = [code_dao.get(code_id) for code_id in race_code_ids]
      race = get_race(race_codes)
      if race != participant_summary.race:
        participant_summary.race = race
        something_changed = True

    # Set summary fields to SUBMITTED for questionnaire concepts that are found in
    # QUESTIONNAIRE_MODULE_CODE_TO_FIELD
    module_changed = False
    for concept in questionnaire_history.concepts:
      code = code_map.get(concept.codeId)
      if code:
        summary_field = QUESTIONNAIRE_MODULE_CODE_TO_FIELD.get(code.value)
        if summary_field:
          new_status = QuestionnaireStatus.SUBMITTED
          if code.value == CONSENT_FOR_ELECTRONIC_HEALTH_RECORDS_MODULE and not ehr_consent:
            new_status = QuestionnaireStatus.SUBMITTED_NO_CONSENT
          if getattr(participant_summary, summary_field) != new_status:
            setattr(participant_summary, summary_field, new_status)
            setattr(participant_summary, summary_field + 'Time', questionnaire_response.created)
            something_changed = True
            module_changed = True
    if module_changed:
      participant_summary.numCompletedBaselinePPIModules = \
          count_completed_baseline_ppi_modules(participant_summary)
      participant_summary.numCompletedPPIModules = \
          count_completed_ppi_modules(participant_summary)

    if something_changed:
      first_last_email = (
          participant_summary.firstName, participant_summary.lastName, participant_summary.email)
      if not all(first_last_email):
        raise BadRequest(
            'First name (%s), last name (%s), and email address (%s) required for consenting.'
            % tuple(['present' if part else 'missing' for part in first_last_email]))
      ParticipantSummaryDao().update_enrollment_status(participant_summary)
      participant_summary.lastModified = clock.CLOCK.now()
      session.merge(participant_summary)
class CodeDaoTest(SqlTestBase):
    def setUp(self):
        super(CodeDaoTest, self).setUp()
        self.code_book_dao = CodeBookDao()
        self.code_dao = CodeDao()
        self.code_history_dao = CodeHistoryDao()

    def test_get_before_insert(self):
        self.assertIsNone(self.code_book_dao.get(1))
        self.assertIsNone(self.code_dao.get(1))
        self.assertIsNone(self.code_history_dao.get(1))

    def test_insert_without_codebook_or_parent(self):
        code = Code(system="a",
                    value="b",
                    display=u"c",
                    topic=u"d",
                    codeType=CodeType.MODULE,
                    mapped=True)
        with FakeClock(TIME):
            self.code_dao.insert(code)

        expected_code = Code(codeId=1,
                             system="a",
                             value="b",
                             display=u"c",
                             topic=u"d",
                             codeType=CodeType.MODULE,
                             mapped=True,
                             created=TIME)
        self.assertEquals(expected_code.asdict(),
                          self.code_dao.get(1).asdict())

        expected_code_history = CodeHistory(codeHistoryId=1,
                                            codeId=1,
                                            system="a",
                                            value="b",
                                            display=u"c",
                                            topic=u"d",
                                            codeType=CodeType.MODULE,
                                            mapped=True,
                                            created=TIME)
        self.assertEquals(expected_code_history.asdict(),
                          self.code_history_dao.get(1).asdict())

    def test_insert_with_codebook_and_parent(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="a")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)
        expected_code_book = CodeBook(codeBookId=1,
                                      latest=True,
                                      created=TIME,
                                      name="pmi",
                                      version="v1",
                                      system="a")
        self.assertEquals(expected_code_book.asdict(),
                          self.code_book_dao.get(1).asdict())

        code_1 = Code(codeBookId=1,
                      system="a",
                      value="b",
                      display=u"c",
                      topic=u"d",
                      codeType=CodeType.MODULE,
                      mapped=True)
        with FakeClock(TIME_2):
            self.code_dao.insert(code_1)

        expected_code = Code(codeBookId=1,
                             codeId=1,
                             system="a",
                             value="b",
                             display=u"c",
                             topic=u"d",
                             codeType=CodeType.MODULE,
                             mapped=True,
                             created=TIME_2)
        self.assertEquals(expected_code.asdict(),
                          self.code_dao.get(1).asdict())

        expected_code_history = CodeHistory(codeBookId=1,
                                            codeHistoryId=1,
                                            codeId=1,
                                            system="a",
                                            value=u"b",
                                            display=u"c",
                                            topic=u"d",
                                            codeType=CodeType.MODULE,
                                            mapped=True,
                                            created=TIME_2)
        self.assertEquals(expected_code_history.asdict(),
                          self.code_history_dao.get(1).asdict())

        code_2 = Code(codeBookId=1,
                      system="x",
                      value="y",
                      display=u"z",
                      topic=u"q",
                      codeType=CodeType.QUESTION,
                      mapped=False,
                      parentId=1)
        with FakeClock(TIME_3):
            self.code_dao.insert(code_2)

        expected_code_2 = Code(codeBookId=1,
                               codeId=2,
                               system="x",
                               value="y",
                               display=u"z",
                               topic=u"q",
                               codeType=CodeType.QUESTION,
                               mapped=False,
                               created=TIME_3,
                               parentId=1)
        self.assertEquals(expected_code_2.asdict(),
                          self.code_dao.get(2).asdict())

    def test_insert_second_codebook_same_system(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="a")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)

        code_book_2 = CodeBook(name="pmi", version="v2", system="a")
        with FakeClock(TIME_2):
            self.code_book_dao.insert(code_book_2)

        expected_code_book = CodeBook(codeBookId=1,
                                      latest=False,
                                      created=TIME,
                                      name="pmi",
                                      version="v1",
                                      system="a")
        self.assertEquals(expected_code_book.asdict(),
                          self.code_book_dao.get(1).asdict())

        expected_code_book_2 = CodeBook(codeBookId=2,
                                        latest=True,
                                        created=TIME_2,
                                        name="pmi",
                                        version="v2",
                                        system="a")
        self.assertEquals(expected_code_book_2.asdict(),
                          self.code_book_dao.get(2).asdict())

    def test_insert_second_codebook_different_system(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="a")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)

        code_book_2 = CodeBook(name="pmi", version="v2", system="b")
        with FakeClock(TIME_2):
            self.code_book_dao.insert(code_book_2)

        expected_code_book = CodeBook(codeBookId=1,
                                      latest=True,
                                      created=TIME,
                                      name="pmi",
                                      version="v1",
                                      system="a")
        self.assertEquals(expected_code_book.asdict(),
                          self.code_book_dao.get(1).asdict())

        expected_code_book_2 = CodeBook(codeBookId=2,
                                        latest=True,
                                        created=TIME_2,
                                        name="pmi",
                                        version="v2",
                                        system="b")
        self.assertEquals(expected_code_book_2.asdict(),
                          self.code_book_dao.get(2).asdict())

    def test_insert_second_codebook_same_system_same_version(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="a")
        self.code_book_dao.insert(code_book_1)

        code_book_2 = CodeBook(name="pmi", version="v1", system="a")
        with self.assertRaises(BadRequest):
            self.code_book_dao.insert(code_book_2)

    def test_update_codes_no_codebook_id(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="c")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)
        code_1 = Code(codeBookId=1,
                      system="a",
                      value="b",
                      display=u"c",
                      topic=u"d",
                      codeType=CodeType.MODULE,
                      mapped=True)
        with FakeClock(TIME_2):
            self.code_dao.insert(code_1)

        new_code_1 = Code(codeId=1,
                          system="x",
                          value="b",
                          display=u"c",
                          topic=u"d",
                          codeType=CodeType.MODULE,
                          mapped=True)
        with self.assertRaises(BadRequest):
            self.code_dao.update(new_code_1)

    def test_update_codes_same_codebook_id(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="c")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)
        code_1 = Code(codeBookId=1,
                      system="a",
                      value="b",
                      display=u"c",
                      topic=u"d",
                      codeType=CodeType.MODULE,
                      mapped=True)
        with FakeClock(TIME_2):
            self.code_dao.insert(code_1)

        new_code_1 = Code(codeBookId=1,
                          codeId=1,
                          system="x",
                          value="b",
                          display=u"c",
                          topic=u"d",
                          codeType=CodeType.MODULE,
                          mapped=True)
        with self.assertRaises(BadRequest):
            self.code_dao.update(new_code_1)

    def test_update_codes_new_codebook_id(self):
        code_book_1 = CodeBook(name="pmi", version="v1", system="a")
        with FakeClock(TIME):
            self.code_book_dao.insert(code_book_1)
        code_1 = Code(codeBookId=1,
                      system="a",
                      value="b",
                      display=u"c",
                      topic=u"d",
                      codeType=CodeType.MODULE,
                      mapped=True)
        with FakeClock(TIME_2):
            self.code_dao.insert(code_1)

        code_book_2 = CodeBook(name="pmi", version="v2", system="a")
        with FakeClock(TIME_3):
            self.code_book_dao.insert(code_book_2)

        new_code_1 = Code(codeBookId=2,
                          codeId=1,
                          system="x",
                          value="b",
                          display=u"c",
                          topic=u"d",
                          codeType=CodeType.MODULE,
                          mapped=True)
        with FakeClock(TIME_4):
            self.code_dao.update(new_code_1)

        expected_code = Code(codeBookId=2,
                             codeId=1,
                             system="x",
                             value="b",
                             display=u"c",
                             topic=u"d",
                             codeType=CodeType.MODULE,
                             mapped=True,
                             created=TIME_2)
        self.assertEquals(expected_code.asdict(),
                          self.code_dao.get(1).asdict())

        expected_code_history = CodeHistory(codeBookId=1,
                                            codeHistoryId=1,
                                            codeId=1,
                                            system="a",
                                            value="b",
                                            display=u"c",
                                            topic=u"d",
                                            codeType=CodeType.MODULE,
                                            mapped=True,
                                            created=TIME_2)
        self.assertEquals(expected_code_history.asdict(),
                          self.code_history_dao.get(1).asdict())

        expected_code_history_2 = CodeHistory(codeHistoryId=2,
                                              codeBookId=2,
                                              codeId=1,
                                              system="x",
                                              value="b",
                                              display=u"c",
                                              topic=u"d",
                                              codeType=CodeType.MODULE,
                                              mapped=True,
                                              created=TIME_2)
        self.assertEquals(expected_code_history_2.asdict(),
                          self.code_history_dao.get(2).asdict())

    def test_import_codebook(self):
        answer_1 = _make_concept(u"t1", "Answer", "c1", u"d1")
        answer_2 = _make_concept(u"t2", "Answer", "c2", u"d2")
        answer_3 = _make_concept(u"t2", "Answer", "c3", u"d3")
        question_1 = _make_concept(u"t1", "Question", "q1", u"d4", [answer_1])
        question_2 = _make_concept(u"t2", "Question", "q2", u"d5",
                                   [answer_2, answer_3])
        topic_1 = _make_concept(u"t1", "Topic", "t1", u"d6", [question_1])
        module_1 = _make_concept(u"mt1", "Module Name", "m1", u"d7", [topic_1])
        module_2 = _make_concept(u"mt2", "Module Name", "m2", u"d8",
                                 [question_2])
        system = 'http://blah/foo'
        codebook = {
            'name': 'pmi',
            'version': 'v1',
            'url': system,
            'concept': [module_1, module_2]
        }
        with FakeClock(TIME):
            self.code_book_dao.import_codebook(codebook)

        expectedCodeBook = CodeBook(codeBookId=1,
                                    latest=True,
                                    created=TIME,
                                    name="pmi",
                                    version="v1",
                                    system=system)
        self.assertEquals(expectedCodeBook.asdict(),
                          self.code_book_dao.get(1).asdict())

        expectedModule1 = Code(codeBookId=1,
                               codeId=1,
                               system=system,
                               value="m1",
                               shortValue="m1",
                               display=u"d7",
                               topic=u"mt1",
                               codeType=CodeType.MODULE,
                               mapped=True,
                               created=TIME)
        self.assertEquals(expectedModule1.asdict(),
                          self.code_dao.get(1).asdict())

        expectedModuleHistory1 = CodeHistory(codeHistoryId=1,
                                             codeBookId=1,
                                             codeId=1,
                                             system=system,
                                             value="m1",
                                             shortValue="m1",
                                             display=u"d7",
                                             topic=u"mt1",
                                             codeType=CodeType.MODULE,
                                             mapped=True,
                                             created=TIME)
        self.assertEquals(expectedModuleHistory1.asdict(),
                          self.code_history_dao.get(1).asdict())

        expectedTopic1 = Code(codeBookId=1,
                              codeId=2,
                              system=system,
                              value="t1",
                              shortValue="t1",
                              display=u"d6",
                              topic=u"t1",
                              codeType=CodeType.TOPIC,
                              mapped=True,
                              created=TIME,
                              parentId=1)
        self.assertEquals(expectedTopic1.asdict(),
                          self.code_dao.get(2).asdict())

        expectedQuestion1 = Code(codeBookId=1,
                                 codeId=3,
                                 system=system,
                                 value="q1",
                                 shortValue="q1",
                                 display=u"d4",
                                 topic=u"t1",
                                 codeType=CodeType.QUESTION,
                                 mapped=True,
                                 created=TIME,
                                 parentId=2)
        self.assertEquals(expectedQuestion1.asdict(),
                          self.code_dao.get(3).asdict())

        expectedAnswer1 = Code(codeBookId=1,
                               codeId=4,
                               system=system,
                               value="c1",
                               shortValue="c1",
                               display=u"d1",
                               topic=u"t1",
                               codeType=CodeType.ANSWER,
                               mapped=True,
                               created=TIME,
                               parentId=3)
        self.assertEquals(expectedAnswer1.asdict(),
                          self.code_dao.get(4).asdict())