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 from_client_json(cls, resource_json, id_=None, expected_version=None, client_id=None): #pylint: disable=unused-argument # Parse the questionnaire to make sure it's valid, but preserve the original JSON # when saving. fhir_q = fhirclient.models.questionnaire.Questionnaire(resource_json) if not fhir_q.group: raise BadRequest('No top-level group found in questionnaire') q = Questionnaire(resource=json.dumps(resource_json), questionnaireId=id_, version=expected_version) # Assemble a map of (system, value) -> (display, code_type, parent_id) for passing into CodeDao. # Also assemble a list of (system, code) for concepts and (system, code, linkId) for questions, # which we'll use later when assembling the child objects. code_map, concepts, questions = cls._extract_codes(fhir_q.group) from dao.code_dao import CodeDao # Get or insert codes, and retrieve their database IDs. add_codes_if_missing = _add_codes_if_missing() code_id_map = CodeDao().get_or_add_codes( code_map, add_codes_if_missing=add_codes_if_missing) # Now add the child objects, using the IDs in code_id_map cls._add_concepts(q, code_id_map, concepts) cls._add_questions(q, code_id_map, questions) return q
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_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 _setup_questionnaire(self): q = Questionnaire(resource=QUESTIONNAIRE_RESOURCE) q.concepts.append(self.CONCEPT_1) q.concepts.append(QuestionnaireConcept(codeId=self.consent_code_id)) q.questions.append(self.CODE_1_QUESTION_1) q.questions.append(self.CODE_2_QUESTION) q.questions.append(self.FN_QUESTION) q.questions.append(self.LN_QUESTION) q.questions.append(self.EMAIL_QUESTION) return self.questionnaire_dao.insert(q)
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)
def test_insert_participant_not_found(self): self.insert_codes() q = Questionnaire(resource=QUESTIONNAIRE_RESOURCE) q.concepts.append(QuestionnaireConcept(codeId=self.consent_code_id)) self.questionnaire_dao.insert(q) qr = QuestionnaireResponse(questionnaireResponseId=1, questionnaireId=1, questionnaireVersion=1, participantId=1, resource=QUESTIONNAIRE_RESPONSE_RESOURCE) qr.answers.extend(self._names_and_email_answers()) # Answers are there but the participant is not. with self.assertRaises(BadRequest): self.questionnaire_response_dao.insert(qr)
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_schema(self): session = self.database.make_session() hpo = HPO(hpoId=1, name='UNSET', displayName='No organization set', organizationType=OrganizationType.UNSET) code_book = CodeBook(codeBookId=1, created=datetime.datetime.now(), latest=True, name="pmi", system="http://foo/bar", version="v0.1.1") session.add(hpo) session.add(code_book) session.commit() organization = Organization(organizationId=1, externalId='org', displayName='Organization', hpoId=1) session.add(organization) session.commit() site = Site(siteId=1, siteName='site', googleGroup='*****@*****.**', mayolinkClientNumber=12345, organizationId=1) code1 = Code(codeId=1, codeBookId=1, system="a", value="b", shortValue="q", display=u"c", topic=u"d", codeType=CodeType.MODULE, mapped=True, created=datetime.datetime.now()) codeHistory1 = CodeHistory(codeId=1, codeBookId=1, system="a", value="b", shortValue="q", display=u"c", topic=u"d", codeType=CodeType.MODULE, mapped=True, created=datetime.datetime.now()) session.add(site) session.add(code1) session.add(codeHistory1) session.commit() code2 = Code(codeId=2, codeBookId=1, parentId=1, system="a", value="c", display=u"X", topic=u"d", codeType=CodeType.QUESTION, mapped=True, created=datetime.datetime.now()) codeHistory2 = CodeHistory(codeId=2, codeBookId=1, parentId=1, system="a", value="c", display=u"X", topic=u"d", codeType=CodeType.QUESTION, mapped=True, created=datetime.datetime.now()) session.add(code2) session.add(codeHistory2) session.commit() code3 = Code(codeId=3, codeBookId=1, parentId=2, system="a", value="d", display=u"Y", topic=u"d", codeType=CodeType.ANSWER, mapped=False, created=datetime.datetime.now()) codeHistory3 = CodeHistory(codeId=3, codeBookId=1, parentId=2, system="a", value="d", display=u"Y", topic=u"d", codeType=CodeType.ANSWER, mapped=False, created=datetime.datetime.now()) session.add(code3) session.add(codeHistory3) session.commit() session.commit() p = self._participant_with_defaults( participantId=1, version=1, biobankId=2, clientId='*****@*****.**', hpoId=hpo.hpoId, signUpTime=datetime.datetime.now(), lastModified=datetime.datetime.now()) ps = self._participant_summary_with_defaults( participantId=1, biobankId=2, lastModified=datetime.datetime.now(), hpoId=hpo.hpoId, firstName=self.fake.first_name(), middleName=self.fake.first_name(), lastName=self.fake.last_name(), email=self.fake.email(), zipCode='78751', dateOfBirth=datetime.date.today(), genderIdentityId=1, consentForStudyEnrollment=QuestionnaireStatus.SUBMITTED, consentForStudyEnrollmentTime=datetime.datetime.now(), numBaselineSamplesArrived=2) p.participantSummary = ps session.add(p) ph = self._participant_history_with_defaults( participantId=1, biobankId=2, clientId='*****@*****.**', hpoId=hpo.hpoId, signUpTime=datetime.datetime.now(), lastModified=datetime.datetime.now()) session.add(ph) session.commit() session.add( BiobankStoredSample(biobankStoredSampleId='WEB1234542', biobankId=p.biobankId, biobankOrderIdentifier='KIT', test='1UR10', confirmed=datetime.datetime.utcnow())) session.add( BiobankStoredSample( biobankStoredSampleId='WEB99999', # Sample ID must be unique. biobankId=p. biobankId, # Participant ID and test may be duplicated. biobankOrderIdentifier='KIT', test='1UR10', confirmed=datetime.datetime.utcnow())) pm = PhysicalMeasurements(physicalMeasurementsId=1, participantId=1, created=datetime.datetime.now(), resource='blah', final=False, logPosition=LogPosition()) pm2 = PhysicalMeasurements(physicalMeasurementsId=2, participantId=1, created=datetime.datetime.now(), resource='blah', final=True, amendedMeasurementsId=1, logPosition=LogPosition()) session.add(pm) session.add(pm2) session.commit() q1 = Measurement(measurementId=3, physicalMeasurementsId=pm.physicalMeasurementsId, codeSystem='codeSystem', codeValue='codeValue', measurementTime=datetime.datetime.now(), valueCodeSystem='valueCodeSystem', valueCodeValue='value3') session.add(q1) session.commit() m1 = Measurement(measurementId=1, physicalMeasurementsId=pm.physicalMeasurementsId, codeSystem='codeSystem', codeValue='codeValue', measurementTime=datetime.datetime.now(), bodySiteCodeSystem='bodySiteCodeSystem', bodySiteCodeValue='bodySiteCodeValue', valueString='a', valueDecimal=1.2, valueUnit='cm', valueCodeSystem='valueCodeSystem', valueCodeValue='value', valueDateTime=datetime.datetime.now(), qualifierId=q1.measurementId) session.add(m1) session.commit() m2 = Measurement(measurementId=2, physicalMeasurementsId=pm.physicalMeasurementsId, codeSystem='codeSystem', codeValue='codeValue', measurementTime=datetime.datetime.now(), valueCodeSystem='valueCodeSystem', valueCodeValue='value2', parentId=m1.measurementId, qualifierId=q1.measurementId) session.add(m2) session.commit() q = Questionnaire(questionnaireId=1, version=1, created=datetime.datetime.now(), lastModified=datetime.datetime.now(), resource='what?') qh = QuestionnaireHistory(questionnaireId=1, version=1, created=datetime.datetime.now(), lastModified=datetime.datetime.now(), resource='what?') qh.questions.append( QuestionnaireQuestion(questionnaireQuestionId=1, questionnaireId=1, questionnaireVersion=1, linkId="1.2.3", codeId=2, repeats=True)) qh.concepts.append( QuestionnaireConcept(questionnaireConceptId=1, questionnaireId=1, questionnaireVersion=1, codeId=1)) session.add(q) session.add(qh) session.commit() qr = QuestionnaireResponse(questionnaireResponseId=1, questionnaireId=1, questionnaireVersion=1, participantId=1, created=datetime.datetime.now(), resource='blah') qr.answers.append( QuestionnaireResponseAnswer(questionnaireResponseAnswerId=1, questionnaireResponseId=1, questionId=1, endTime=datetime.datetime.now(), valueSystem='a', valueCodeId=3, valueDecimal=123, valueString=self.fake.first_name(), valueDate=datetime.date.today())) session.add(qr) session.commit() mv = MetricsVersion(metricsVersionId=1, inProgress=False, complete=True, date=datetime.datetime.utcnow(), dataVersion=1) session.add(mv) session.commit() mb = MetricsBucket(metricsVersionId=1, date=datetime.date.today(), hpoId='PITT', metrics='blah') session.add(mb) session.commit()
def test_insert_qr_three_times(self): """Adds three questionnaire responses for the same participant. The latter two responses are for the same questionnaire, answering a question that has the same concept code and system as a question found on the first (different) questionnaire. Verifies that new answers set endTime on answers for questions with the same concept for the same participant, whether on the same questionnaire or a different questionnaire, without affecting other answers. """ self.insert_codes() p = Participant(participantId=1, biobankId=2) with FakeClock(TIME): self.participant_dao.insert(p) self._setup_questionnaire() q2 = Questionnaire(resource=QUESTIONNAIRE_RESOURCE_2) # The question on the second questionnaire has the same concept as the first question on the # first questionnaire; answers to it will thus set endTime for answers to the first question. q2.questions.append(self.CODE_1_QUESTION_2) self.questionnaire_dao.insert(q2) qr = QuestionnaireResponse(questionnaireResponseId=1, questionnaireId=1, questionnaireVersion=1, participantId=1, resource=QUESTIONNAIRE_RESPONSE_RESOURCE) answer_1 = QuestionnaireResponseAnswer( questionnaireResponseAnswerId=1, questionnaireResponseId=1, questionId=1, valueSystem='a', valueCodeId=3, valueDecimal=123, valueString=self.fake.first_name(), valueDate=datetime.date.today()) answer_2 = QuestionnaireResponseAnswer(questionnaireResponseAnswerId=2, questionnaireResponseId=1, questionId=2, valueSystem='c', valueCodeId=4) qr.answers.append(answer_1) qr.answers.append(answer_2) qr.answers.extend(self._names_and_email_answers()) with FakeClock(TIME_2): self.questionnaire_response_dao.insert(qr) expected_ps = self._participant_summary_with_defaults( participantId=1, biobankId=2, genderIdentityId=3, signUpTime=TIME, numCompletedBaselinePPIModules=1, numCompletedPPIModules=1, questionnaireOnTheBasics=QuestionnaireStatus.SUBMITTED, questionnaireOnTheBasicsTime=TIME_2, questionnaireOnTheBasicsAuthored=TIME_2, consentForStudyEnrollment=QuestionnaireStatus.SUBMITTED, consentForStudyEnrollmentTime=TIME_2, consentForStudyEnrollmentAuthored=TIME_2, lastModified=TIME_2, firstName=self.first_name, lastName=self.last_name, email=self.email) self.assertEquals(expected_ps.asdict(), self.participant_summary_dao.get(1).asdict()) qr2 = QuestionnaireResponse(questionnaireResponseId=2, questionnaireId=2, questionnaireVersion=1, participantId=1, resource=QUESTIONNAIRE_RESPONSE_RESOURCE_2) answer_3 = QuestionnaireResponseAnswer( questionnaireResponseAnswerId=6, questionnaireResponseId=2, questionId=7, valueSystem='x', valueCodeId=5, valueDecimal=123, valueString=self.fake.last_name(), valueDate=datetime.date.today()) qr2.answers.append(answer_3) with FakeClock(TIME_3): qr2.authored = TIME_3 self.questionnaire_response_dao.insert(qr2) expected_qr = QuestionnaireResponse( questionnaireResponseId=1, questionnaireId=1, questionnaireVersion=1, participantId=1, resource=with_id(QUESTIONNAIRE_RESPONSE_RESOURCE, 1), created=TIME_2, authored=TIME_2) # Answer one on the original response should be marked as ended, since a question with # the same concept was answered. Answer two should be left alone. answer_1.endTime = TIME_3 expected_qr.answers.append(answer_1) expected_qr.answers.append(answer_2) expected_qr.answers.extend(self._names_and_email_answers()) self.check_response(expected_qr) # The new questionnaire response should be there, too. expected_qr2 = QuestionnaireResponse( questionnaireResponseId=2, questionnaireId=2, questionnaireVersion=1, participantId=1, resource=with_id(QUESTIONNAIRE_RESPONSE_RESOURCE_2, 2), created=TIME_3, authored=TIME_3) expected_qr2.answers.append(answer_3) self.check_response(expected_qr2) expected_ps2 = self._participant_summary_with_defaults( participantId=1, biobankId=2, genderIdentityId=5, signUpTime=TIME, numCompletedBaselinePPIModules=1, numCompletedPPIModules=1, questionnaireOnTheBasics=QuestionnaireStatus.SUBMITTED, questionnaireOnTheBasicsTime=TIME_2, questionnaireOnTheBasicsAuthored=TIME_2, lastModified=TIME_3, consentForStudyEnrollment=QuestionnaireStatus.SUBMITTED, consentForStudyEnrollmentTime=TIME_2, consentForStudyEnrollmentAuthored=TIME_2, firstName=self.first_name, lastName=self.last_name, email=self.email) # The participant summary should be updated with the new gender identity, but nothing else # changes. self.assertEquals(expected_ps2.asdict(), self.participant_summary_dao.get(1).asdict()) qr3 = QuestionnaireResponse(questionnaireResponseId=3, questionnaireId=2, questionnaireVersion=1, participantId=1, resource=QUESTIONNAIRE_RESPONSE_RESOURCE_3) answer_4 = QuestionnaireResponseAnswer( questionnaireResponseAnswerId=7, questionnaireResponseId=3, questionId=7, valueSystem='z', valueCodeId=6, valueDecimal=456, valueString=self.fake.last_name(), valueDate=datetime.date.today()) qr3.answers.append(answer_4) with FakeClock(TIME_4): qr3.authored = TIME_4 self.questionnaire_response_dao.insert(qr3) # The first questionnaire response hasn't changed. self.check_response(expected_qr) # The second questionnaire response's answer should have had an endTime set. answer_3.endTime = TIME_4 self.check_response(expected_qr2) # The third questionnaire response should be there. expected_qr3 = QuestionnaireResponse( questionnaireResponseId=3, questionnaireId=2, questionnaireVersion=1, participantId=1, resource=with_id(QUESTIONNAIRE_RESPONSE_RESOURCE_3, 3), created=TIME_4, authored=TIME_4) expected_qr3.answers.append(answer_4) self.check_response(expected_qr3) expected_ps3 = self._participant_summary_with_defaults( participantId=1, biobankId=2, genderIdentityId=6, signUpTime=TIME, numCompletedBaselinePPIModules=1, numCompletedPPIModules=1, questionnaireOnTheBasics=QuestionnaireStatus.SUBMITTED, questionnaireOnTheBasicsTime=TIME_2, questionnaireOnTheBasicsAuthored=TIME_2, consentForStudyEnrollment=QuestionnaireStatus.SUBMITTED, consentForStudyEnrollmentTime=TIME_2, consentForStudyEnrollmentAuthored=TIME_2, lastModified=TIME_4, firstName=self.first_name, lastName=self.last_name, email=self.email) # The participant summary should be updated with the new gender identity, but nothing else # changes. self.assertEquals(expected_ps3.asdict(), self.participant_summary_dao.get(1).asdict())