def setUp(self):
     super(ParticipantSummaryDaoTest, self).setUp(use_mysql=True)
     self.dao = ParticipantSummaryDao()
     self.order_dao = BiobankOrderDao()
     self.measurement_dao = PhysicalMeasurementsDao()
     self.participant_dao = ParticipantDao()
     self.no_filter_query = Query([], None, 2, None)
     self.one_filter_query = Query(
         [FieldFilter("participantId", Operator.EQUALS, 1)], None, 2, None)
     self.two_filter_query = Query([
         FieldFilter("participantId", Operator.EQUALS, 1),
         FieldFilter("hpoId", Operator.EQUALS, PITT_HPO_ID)
     ], None, 2, None)
     self.ascending_biobank_id_query = Query([], OrderBy("biobankId", True),
                                             2, None)
     self.descending_biobank_id_query = Query([],
                                              OrderBy("biobankId",
                                                      False), 2, None)
     self.enrollment_status_order_query = Query([],
                                                OrderBy(
                                                    "enrollmentStatus",
                                                    True), 2, None)
     self.hpo_id_order_query = Query([], OrderBy("hpoId", True), 2, None)
     self.first_name_order_query = Query([], OrderBy("firstName", True), 2,
                                         None)
Example #2
0
 def setUp(self):
   super(PhysicalMeasurementsDaoTest, self).setUp()
   self.participant = Participant(participantId=1, biobankId=2)
   ParticipantDao().insert(self.participant)
   self.dao = PhysicalMeasurementsDao()
   self.participant_summary_dao = ParticipantSummaryDao()
   self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                            TIME_1.isoformat()))
   self.biobank = BiobankOrderDao()
    def test_update_with_patch_cancel(self):
        self._make_summary()
        summary = ParticipantSummaryDao().get(self.participant.participantId)
        self.assertIsNone(summary.physicalMeasurementsStatus)
        with FakeClock(TIME_2):
            measurements = self.dao.insert(self._make_physical_measurements())

        cancel = get_restore_or_cancel_info()
        with FakeClock(TIME_3):
            with PhysicalMeasurementsDao().session() as session:
                update = self.dao.update_with_patch(
                    measurements.physicalMeasurementsId, session, cancel)
        self.assertEqual(update.status, PhysicalMeasurementsStatus.CANCELLED)
        self.assertEqual(update.reason, cancel['reason'])
        self.assertEqual(update.cancelledSiteId, 1)
        self.assertEqual(update.cancelledTime, TIME_3)
        self.assertEqual(update.cancelledUsername,
                         cancel['cancelledInfo']['author']['value'])

        summary = ParticipantSummaryDao().get(self.participant.participantId)
        self.assertEqual(summary.physicalMeasurementsStatus,
                         PhysicalMeasurementsStatus.CANCELLED)
        self.assertEqual(summary.physicalMeasurementsTime, None)
        self.assertEqual(summary.physicalMeasurementsFinalizedTime, TIME_1)
        self.assertEqual(summary.physicalMeasurementsCreatedSiteId, 1)
        self.assertEqual(summary.physicalMeasurementsFinalizedSiteId, 2)
Example #4
0
  def test_insert(self):
    self.send_consent(self.participant_id)
    self.send_consent(self.participant_id_2)
    # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    now = self.time1
    self._insert_measurements(now.isoformat())

    response = self.send_get('Participant/%s/PhysicalMeasurements' % self.participant_id)
    self.assertEquals('Bundle', response['resourceType'])
    self.assertEquals('searchset', response['type'])
    self.assertFalse(response.get('link'))
    self.assertTrue(response.get('entry'))
    self.assertEquals(1, len(response['entry']))

    physical_measurements_id = response['entry'][0]['resource']['id']
    pm_id = int(physical_measurements_id)
    physical_measurements = PhysicalMeasurementsDao().get_with_children(physical_measurements_id)
    self.assertEquals(physical_measurements.createdSiteId, 1)
    self.assertIsNone(physical_measurements.createdUsername)
    self.assertEquals(physical_measurements.finalizedSiteId, 2)
    self.assertIsNone(physical_measurements.finalizedUsername)

    em1 = Measurement(measurementId=pm_id * 1000,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-measurements",
                      codeValue="systolic-diastolic-blood-pressure-1",
                      measurementTime=now,
                      bodySiteCodeSystem="http://snomed.info/sct",
                      bodySiteCodeValue="368209003")
    bp1 = Measurement(measurementId=pm_id * 1000 + 1,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-measurements",
                      codeValue="systolic-blood-pressure-1",
                      measurementTime=now,
                      valueDecimal=109.0,
                      valueUnit="mm[Hg]",
                      parentId=em1.measurementId)
    bp2 = Measurement(measurementId=pm_id * 1000 + 2,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="8462-4",
                      measurementTime=now,
                      valueDecimal=44.0,
                      valueUnit="mm[Hg]",
                      parentId=em1.measurementId)
    m1 = physical_measurements.measurements[0]
    self.assertEquals(em1.asdict(), m1.asdict())
    self.assertEquals(2, len(m1.measurements))
    self.assertEquals(bp1.asdict(), m1.measurements[0].asdict())
    self.assertEquals(bp2.asdict(), m1.measurements[1].asdict())

    response = self.send_get('Participant/%s/PhysicalMeasurements' % self.participant_id_2)
    self.assertEquals('Bundle', response['resourceType'])
    self.assertEquals('searchset', response['type'])
    self.assertFalse(response.get('link'))
    self.assertTrue(response.get('entry'))
    self.assertEquals(1, len(response['entry']))
    def calculate_distinct_visits(self,
                                  pid,
                                  finalized_time,
                                  id_,
                                  amendment=False):
        """ Participants may get PM or biobank samples on same day. This should be considered as
    a single visit in terms of program payment to participant.
    return Boolean: true if there has not been an order on same date."""
        from dao.biobank_order_dao import BiobankOrderDao
        from dao.physical_measurements_dao import PhysicalMeasurementsDao

        day_has_order, day_has_measurement = False, False
        existing_orders = BiobankOrderDao().get_biobank_orders_for_participant(
            pid)
        ordered_samples = BiobankOrderDao(
        ).get_ordered_samples_for_participant(pid)
        existing_measurements = PhysicalMeasurementsDao(
        ).get_measuremnets_for_participant(pid)

        order_id_to_finalized_date = {
            sample.biobankOrderId: sample.finalized.date()
            for sample in ordered_samples if sample.finalized
        }

        if existing_orders and finalized_time:
            for order in existing_orders:
                order_finalized_date = order_id_to_finalized_date.get(
                    order.biobankOrderId)
                if order_finalized_date == finalized_time.date() and order.biobankOrderId != id_ and \
                  order.orderStatus != BiobankOrderStatus.CANCELLED:
                    day_has_order = True
                elif order.biobankOrderId == id_ and order.orderStatus == BiobankOrderStatus.AMENDED:
                    day_has_order = True
        elif not finalized_time and amendment:
            day_has_order = True

        if existing_measurements and finalized_time:
            for measurement in existing_measurements:
                if not measurement.finalized:
                    continue
                if measurement.finalized.date() == finalized_time.date() and measurement.physicalMeasurementsId\
                  != id_:
                    day_has_measurement = True

        is_distinct_visit = not (day_has_order or day_has_measurement)
        return is_distinct_visit
Example #6
0
    def setUp(self):

        super(BigQuerySyncDaoTest, self).setUp(use_mysql=True,
                                               with_consent_codes=True)
        self.dao = ParticipantDao()

        with self.dao.session() as session:
            self.site = session.query(Site).filter(
                Site.googleGroup == 'hpo-site-monroeville').first()
            self.hpo = session.query(HPO).filter(HPO.name == 'PITT').first()

        with clock.FakeClock(self.TIME_1):
            self.participant = Participant(participantId=123, biobankId=555)
            self.participant.hpoId = self.hpo.hpoId
            self.participant.siteId = self.site.siteId
            self.dao.insert(self.participant)

            ps = ParticipantSummary(
                participantId=123,
                biobankId=555,
                firstName='john',
                lastName='doe',
                withdrawalStatus=WithdrawalStatus.NOT_WITHDRAWN,
                suspensionStatus=SuspensionStatus.NOT_SUSPENDED)
            ps.hpoId = self.hpo.hpoId
            ps.siteId = self.site.siteId
            self.summary = ParticipantSummaryDao().insert(ps)

        self.pm_json = json.dumps(
            load_measurement_json(self.participant.participantId,
                                  self.TIME_1.isoformat()))
        self.pm = PhysicalMeasurementsDao().insert(
            self._make_physical_measurements())

        with clock.FakeClock(self.TIME_2):
            self.dao = BiobankOrderDao()
            self.bio_order = BiobankOrderDao().insert(
                self._make_biobank_order(
                    participantId=self.participant.participantId))
Example #7
0
  def test_insert_with_qualifiers(self):
    self.send_consent(self.participant_id)
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    now = self.time2
    with open(data_path('physical_measurements_2.json')) as measurements_file:
      json_text = measurements_file.read() % {
        'participant_id': self.participant_id,
        'authored_time': now.isoformat()
      }
    measurements_json = json.loads(json_text)
    path_1 = 'Participant/%s/PhysicalMeasurements' % self.participant_id
    self.send_post(path_1, measurements_json)

    response = self.send_get('Participant/%s/PhysicalMeasurements' % self.participant_id)
    self.assertEquals('Bundle', response['resourceType'])
    self.assertEquals('searchset', response['type'])
    self.assertFalse(response.get('link'))
    self.assertTrue(response.get('entry'))
    self.assertEquals(1, len(response['entry']))

    physical_measurements_id = response['entry'][0]['resource']['id']
    pm_id = int(physical_measurements_id)
    physical_measurements = PhysicalMeasurementsDao().get_with_children(physical_measurements_id)
    self.assertEquals(physical_measurements.finalizedSiteId, 1)
    self.assertEquals('*****@*****.**', physical_measurements.finalizedUsername)
    # Site not present in DB, so we don't set it.
    self.assertIsNone(physical_measurements.createdSiteId)
    self.assertEquals('*****@*****.**', physical_measurements.createdUsername)

    em1_id = pm_id * 1000
    bp1 = Measurement(measurementId=pm_id * 1000 + 1,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="8480-6",
                      measurementTime=now,
                      valueDecimal=109.0,
                      valueUnit="mm[Hg]",
                      parentId=em1_id)
    bp2 = Measurement(measurementId=pm_id * 1000 + 2,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="8462-4",
                      measurementTime=now,
                      valueDecimal=44.0,
                      valueUnit="mm[Hg]",
                      parentId=em1_id)
    bp3 = Measurement(measurementId=pm_id * 1000 + 3,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-evaluation",
                      codeValue="arm-circumference",
                      measurementTime=now,
                      valueDecimal=32.0,
                      valueUnit="cm",
                      parentId=em1_id)
    em1 = Measurement(measurementId=pm_id * 1000,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="55284-4",
                      measurementTime=now,
                      bodySiteCodeSystem="http://snomed.info/sct",
                      bodySiteCodeValue="368209003",
                      measurements = [bp1, bp2, bp3])

    pm_height_system = "http://terminology.pmi-ops.org/CodeSystem/protocol-modifications-height"
    q1 = Measurement(measurementId=pm_id * 1000 + 4,
                     physicalMeasurementsId=pm_id,
                     codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-evaluation",
                     codeValue="protocol-modifications-height",
                     measurementTime=now,
                     valueCodeSystem=pm_height_system,
                     valueCodeValue="hair-style")

    em2 = Measurement(measurementId=pm_id * 1000 + 5,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-evaluation",
                      codeValue="pre-pregnancy-weight",
                      measurementTime=now,
                      valueDecimal=28.0,
                      valueUnit="kg")
    pm_weight_system = "http://terminology.pmi-ops.org/CodeSystem/protocol-modifications-weight"
    q2 = Measurement(measurementId=pm_id * 1000 + 6,
                     physicalMeasurementsId=pm_id,
                     codeSystem="http://terminology.pmi-ops.org/CodeSystem/physical-evaluation",
                     codeValue="protocol-modifications-weight",
                     measurementTime=now,
                     valueCodeSystem=pm_weight_system,
                     valueCodeValue="other")
    em3 = Measurement(measurementId=pm_id * 1000 + 7,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="39156-5",
                      measurementTime=now,
                      valueDecimal=24.2,
                      valueUnit="kg/m2")
    # Skip a bunch -- could add these later
    em4 = Measurement(measurementId=pm_id * 1000 + 14,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="8302-2",
                      measurementTime=now,
                      valueDecimal=111.5,
                      valueUnit="cm",
                      qualifiers=[q1])
    em5 = Measurement(measurementId=pm_id * 1000 + 15,
                      physicalMeasurementsId=pm_id,
                      codeSystem="http://loinc.org",
                      codeValue="29463-7",
                      measurementTime=now,
                      valueDecimal=30.1,
                      valueUnit="kg",
                      qualifiers=[q2])

    m = {measurement.measurementId:measurement.asdict(follow = {'measurements': {},
                                                                'qualifiers': {}}) for measurement
         in physical_measurements.measurements}

    for em in [em1, bp1, bp2, bp3, q1, em2, q2, em3, em4, em5]:
      self.assertEquals(em.asdict(follow = {'measurements': {},
                                            'qualifiers': {}}), m.get(em.measurementId))
class ParticipantSummaryDaoTest(NdbTestBase):

  def setUp(self):
    super(ParticipantSummaryDaoTest, self).setUp(use_mysql=True)
    self.dao = ParticipantSummaryDao()
    self.order_dao = BiobankOrderDao()
    self.measurement_dao = PhysicalMeasurementsDao()
    self.participant_dao = ParticipantDao()
    self.no_filter_query = Query([], None, 2, None)
    self.one_filter_query = Query([FieldFilter("participantId", Operator.EQUALS, 1)],
                                  None, 2, None)
    self.two_filter_query = Query([FieldFilter("participantId", Operator.EQUALS, 1),
                                   FieldFilter("hpoId", Operator.EQUALS, PITT_HPO_ID)],
                                  None, 2, None)
    self.ascending_biobank_id_query = Query([], OrderBy("biobankId", True), 2, None)
    self.descending_biobank_id_query = Query([], OrderBy("biobankId", False), 2, None)
    self.enrollment_status_order_query = Query([], OrderBy("enrollmentStatus", True), 2, None)
    self.hpo_id_order_query = Query([], OrderBy("hpoId", True), 2, None)
    self.first_name_order_query = Query([], OrderBy("firstName", True), 2, None)

  def assert_no_results(self, query):
    results = self.dao.query(query)
    self.assertEquals([], results.items)
    self.assertIsNone(results.pagination_token)

  def assert_results(self, query, items, pagination_token=None):
    results = self.dao.query(query)
    self.assertListAsDictEquals(items, results.items)
    self.assertEquals(pagination_token, results.pagination_token,
                      "Pagination tokens don't match; decoded = %s, %s" %
                      (_decode_token(pagination_token), _decode_token(results.pagination_token)))

  def test_query_with_total(self):
    num_participants = 5
    query = Query([], None, 10, None, include_total=True)
    results = self.dao.query(query)
    self.assertEqual(results.total, 0)
    for i in range(num_participants):
      participant = Participant(participantId=i, biobankId=i)
      self._insert(participant)
    results = self.dao.query(query)
    self.assertEqual(results.total, num_participants)

  def testQuery_noSummaries(self):
    self.assert_no_results(self.no_filter_query)
    self.assert_no_results(self.one_filter_query)
    self.assert_no_results(self.two_filter_query)
    self.assert_no_results(self.ascending_biobank_id_query)
    self.assert_no_results(self.descending_biobank_id_query)

  def _insert(self, participant, first_name=None, last_name=None):
    self.participant_dao.insert(participant)
    summary = self.participant_summary(participant)
    if first_name:
      summary.firstName = first_name
    if last_name:
      summary.lastName = last_name
    self.dao.insert(summary)
    return participant

  def testQuery_oneSummary(self):
    participant = Participant(participantId=1, biobankId=2)
    self._insert(participant)
    summary = self.dao.get(1)
    self.assert_results(self.no_filter_query, [summary])
    self.assert_results(self.one_filter_query, [summary])
    self.assert_no_results(self.two_filter_query)
    self.assert_results(self.ascending_biobank_id_query, [summary])
    self.assert_results(self.descending_biobank_id_query, [summary])

  def testUnicodeNameRoundTrip(self):
    name = self.fake.first_name()
    with self.assertRaises(UnicodeEncodeError):
      str(name)  # sanity check that the name contains non-ASCII
    participant = self._insert(Participant(participantId=1, biobankId=2))
    summary = self.dao.get(participant.participantId)
    summary.firstName = name
    self.dao.update(summary)
    fetched_summary = self.dao.get(participant.participantId)
    self.assertEquals(name, fetched_summary.firstName)

  def testQuery_twoSummaries(self):
    participant_1 = Participant(participantId=1, biobankId=2)
    self._insert(participant_1, 'Alice', 'Smith')
    participant_2 = Participant(participantId=2, biobankId=1)
    self._insert(participant_2, 'Zed', 'Zebra')
    ps_1 = self.dao.get(1)
    ps_2 = self.dao.get(2)
    self.assert_results(self.no_filter_query, [ps_1, ps_2])
    self.assert_results(self.one_filter_query, [ps_1])
    self.assert_no_results(self.two_filter_query)
    self.assert_results(self.ascending_biobank_id_query, [ps_2, ps_1])
    self.assert_results(self.descending_biobank_id_query, [ps_1, ps_2])

  def testQuery_threeSummaries_paginate(self):
    participant_1 = Participant(participantId=1, biobankId=4)
    self._insert(participant_1, 'Alice', 'Aardvark')
    participant_2 = Participant(participantId=2, biobankId=1)
    self._insert(participant_2, 'Bob', 'Builder')
    participant_3 = Participant(participantId=3, biobankId=3)
    self._insert(participant_3, 'Chad', 'Caterpillar')
    ps_1 = self.dao.get(1)
    ps_2 = self.dao.get(2)
    ps_3 = self.dao.get(3)
    self.assert_results(self.no_filter_query, [ps_1, ps_2],
                        _make_pagination_token(['Builder', 'Bob', None, 2]))
    self.assert_results(self.one_filter_query, [ps_1])
    self.assert_no_results(self.two_filter_query)
    self.assert_results(self.ascending_biobank_id_query, [ps_2, ps_3],
                        _make_pagination_token([3, 'Caterpillar', 'Chad', None, 3]))
    self.assert_results(self.descending_biobank_id_query, [ps_1, ps_3],
                        _make_pagination_token([3, 'Caterpillar', 'Chad', None, 3]))

    self.assert_results(_with_token(self.no_filter_query,
                                    _make_pagination_token(['Builder', 'Bob', None, 2])), [ps_3])
    self.assert_results(_with_token(self.ascending_biobank_id_query,
                                    _make_pagination_token([3, 'Caterpillar', 'Chad', None, 3])),
                        [ps_1])
    self.assert_results(_with_token(self.descending_biobank_id_query,
                                    _make_pagination_token([3, 'Caterpillar', 'Chad', None, 3])),
                        [ps_2])

  def testQuery_fourFullSummaries_paginate(self):
    participant_1 = Participant(participantId=1, biobankId=4)
    self._insert(participant_1, 'Bob', 'Jones')
    participant_2 = Participant(participantId=2, biobankId=1)
    self._insert(participant_2, 'Bob', 'Jones')
    participant_3 = Participant(participantId=3, biobankId=3)
    self._insert(participant_3, 'Bob', 'Jones')
    participant_4 = Participant(participantId=4, biobankId=2)
    self._insert(participant_4, 'Bob', 'Jones')
    ps_1 = self.dao.get(1)
    ps_2 = self.dao.get(2)
    ps_3 = self.dao.get(3)
    ps_4 = self.dao.get(4)

    ps_1.lastName = 'Jones'
    ps_1.firstName = 'Bob'
    ps_1.dateOfBirth = datetime.date(1978, 10, 9)
    ps_1.hpoId = PITT_HPO_ID
    self.dao.update(ps_1)

    ps_2.lastName = 'Aardvark'
    ps_2.firstName = 'Bob'
    ps_2.dateOfBirth = datetime.date(1978, 10, 10)
    ps_2.enrollmentStatus = EnrollmentStatus.MEMBER
    self.dao.update(ps_2)

    ps_3.lastName = 'Jones'
    ps_3.firstName = 'Bob'
    ps_3.dateOfBirth = datetime.date(1978, 10, 10)
    ps_3.hpoId = PITT_HPO_ID
    ps_3.enrollmentStatus = EnrollmentStatus.MEMBER
    self.dao.update(ps_3)

    ps_4.lastName = 'Jones'
    ps_4.enrollmentStatus = EnrollmentStatus.FULL_PARTICIPANT
    self.dao.update(ps_4)

    self.assert_results(self.no_filter_query, [ps_2, ps_4],
                        _make_pagination_token(['Jones', 'Bob', None, 4]))
    self.assert_results(self.one_filter_query, [ps_1])
    self.assert_results(self.two_filter_query, [ps_1])
    self.assert_results(self.ascending_biobank_id_query, [ps_2, ps_4],
                        _make_pagination_token([2, 'Jones', 'Bob', None, 4]))
    self.assert_results(self.descending_biobank_id_query, [ps_1, ps_3],
                        _make_pagination_token([3, 'Jones', 'Bob', datetime.date(1978, 10, 10), 3]))
    self.assert_results(self.hpo_id_order_query, [ps_2, ps_4],
                        _make_pagination_token([0, 'Jones', 'Bob', None, 4]))
    self.assert_results(self.enrollment_status_order_query, [ps_1, ps_2],
                        _make_pagination_token(['MEMBER', 'Aardvark', 'Bob',
                                                datetime.date(1978, 10, 10), 2]))

    self.assert_results(_with_token(self.no_filter_query,
                                    _make_pagination_token(['Jones', 'Bob', None, 4])),
                        [ps_1, ps_3])
    self.assert_results(_with_token(self.ascending_biobank_id_query,
                                    _make_pagination_token([2, 'Jones', 'Bob', None, 4])),
                        [ps_3, ps_1])
    self.assert_results(_with_token(self.descending_biobank_id_query,
                                    _make_pagination_token([3, 'Jones', 'Bob',
                                                            datetime.date(1978, 10, 10), 3])),
                        [ps_4, ps_2])
    self.assert_results(_with_token(self.hpo_id_order_query,
                                    _make_pagination_token([0, 'Jones', 'Bob', None, 4])),
                        [ps_1, ps_3])
    self.assert_results(_with_token(self.enrollment_status_order_query,
                                    _make_pagination_token(['MEMBER', 'Aardvark', 'Bob',
                                                datetime.date(1978, 10, 10), 2])),
                        [ps_3, ps_4])

  def test_update_from_samples(self):
    # baseline_tests = ['BASELINE1', 'BASELINE2']
    baseline_tests = ["1PST8", "2PST8"]

    config.override_setting(config.BASELINE_SAMPLE_TEST_CODES, baseline_tests)
    self.dao.update_from_biobank_stored_samples()  # safe noop

    p_baseline_samples = self._insert(Participant(participantId=1, biobankId=11))
    p_mixed_samples = self._insert(Participant(participantId=2, biobankId=22))
    p_no_samples = self._insert(Participant(participantId=3, biobankId=33))
    p_unconfirmed = self._insert(Participant(participantId=4, biobankId=44))
    self.assertEquals(self.dao.get(p_baseline_samples.participantId).numBaselineSamplesArrived, 0)

    def get_p_baseline_last_modified():
      return self.dao.get(p_baseline_samples.participantId).lastModified
    p_baseline_last_modified1 = get_p_baseline_last_modified()

    sample_dao = BiobankStoredSampleDao()

    def add_sample(participant, test_code, sample_id):
      TIME = datetime.datetime(2018, 3, 2)
      sample_dao.insert(BiobankStoredSample(
          biobankStoredSampleId=sample_id, biobankId=participant.biobankId,
        biobankOrderIdentifier='KIT', test=test_code, confirmed=TIME))

    add_sample(p_baseline_samples, baseline_tests[0], '11111')
    add_sample(p_baseline_samples, baseline_tests[1], '22223')
    add_sample(p_mixed_samples, baseline_tests[0], '11112')
    add_sample(p_mixed_samples, 'NOT1', '44441')
    # add unconfirmed sample
    sample_dao.insert(BiobankStoredSample(biobankStoredSampleId=55555,
                                          biobankId=p_unconfirmed.biobankId,
                                          biobankOrderIdentifier='KIT', test=baseline_tests[1],
                                          confirmed=None))
    # sleep 1 sec to make lastModified different
    time.sleep(1)
    self.dao.update_from_biobank_stored_samples()

    p_baseline_last_modified2 = get_p_baseline_last_modified()
    self.assertNotEquals(p_baseline_last_modified2, p_baseline_last_modified1)

    self.assertEquals(self.dao.get(p_baseline_samples.participantId).numBaselineSamplesArrived, 2)
    self.assertEquals(self.dao.get(p_mixed_samples.participantId).numBaselineSamplesArrived, 1)
    self.assertEquals(self.dao.get(p_no_samples.participantId).numBaselineSamplesArrived, 0)
    self.assertEquals(self.dao.get(p_unconfirmed.participantId).numBaselineSamplesArrived, 0)

    M_baseline_samples = self._insert(Participant(participantId=9, biobankId=99))
    add_sample(M_baseline_samples, baseline_tests[0], '999')
    M_first_update = self.dao.get(M_baseline_samples.participantId)
    # sleep 1 sec to make lastModified different
    time.sleep(1)
    self.dao.update_from_biobank_stored_samples()
    add_sample(M_baseline_samples, baseline_tests[1], '9999')
    M_second_update = self.dao.get(M_baseline_samples.participantId)
    # sleep 1 sec to make lastModified different
    time.sleep(1)
    self.dao.update_from_biobank_stored_samples()

    self.assertNotEqual(M_first_update.lastModified, M_second_update.lastModified)
    self.assertEquals(get_p_baseline_last_modified(), p_baseline_last_modified2)

  def test_update_from_samples_changed_tests(self):
    baseline_tests = ["1PST8", "2PST8"]
    config.override_setting(config.BASELINE_SAMPLE_TEST_CODES, baseline_tests)
    self.dao.update_from_biobank_stored_samples()  # safe noop

    participant = self._insert(Participant(participantId=1, biobankId=11))
    self.assertEquals(self.dao.get(participant.participantId).numBaselineSamplesArrived, 0)

    sample_dao = BiobankStoredSampleDao()
    def add_sample(test_code, sample_id):
      TIME = datetime.datetime(2018, 3, 2)
      sample_dao.insert(BiobankStoredSample(
          biobankStoredSampleId=sample_id, biobankId=participant.biobankId,
          biobankOrderIdentifier='KIT', test=test_code, confirmed=TIME))

    add_sample(baseline_tests[0], '11111')
    add_sample(baseline_tests[1], '22223')
    self.dao.update_from_biobank_stored_samples()
    summary = self.dao.get(participant.participantId)
    init_last_modified = summary.lastModified
    self.assertEquals(summary.numBaselineSamplesArrived, 2)
    # sleep 1 sec to make lastModified different
    time.sleep(1)
    # Simulate removal of one of the baseline tests from config.json.
    baseline_tests.pop()
    config.override_setting(config.BASELINE_SAMPLE_TEST_CODES, baseline_tests)
    self.dao.update_from_biobank_stored_samples()

    summary = self.dao.get(participant.participantId)
    self.assertEquals(summary.numBaselineSamplesArrived, 1)
    self.assertNotEqual(init_last_modified, summary.lastModified)

  def test_only_update_dna_sample(self):
    dna_tests = ["1ED10", "1SAL2"]

    config.override_setting(config.DNA_SAMPLE_TEST_CODES, dna_tests)
    self.dao.update_from_biobank_stored_samples()  # safe noop

    p_dna_samples = self._insert(Participant(participantId=1, biobankId=11))

    self.assertEquals(self.dao.get(p_dna_samples.participantId).samplesToIsolateDNA, None)
    self.assertEquals(
      self.dao.get(p_dna_samples.participantId).enrollmentStatusCoreStoredSampleTime, None)
    self.assertEquals(
      self.dao.get(p_dna_samples.participantId).enrollmentStatusCoreOrderedSampleTime, None)

    sample_dao = BiobankStoredSampleDao()

    def add_sample(participant, test_code, sample_id, confirmed_time):
      sample_dao.insert(BiobankStoredSample(
          biobankStoredSampleId=sample_id, biobankId=participant.biobankId,
          biobankOrderIdentifier='KIT', test=test_code, confirmed=confirmed_time))

    confirmed_time_0 = datetime.datetime(2018, 3, 1)
    add_sample(p_dna_samples, dna_tests[0], '11111', confirmed_time_0)

    self.dao.update_from_biobank_stored_samples()

    self.assertEquals(self.dao.get(p_dna_samples.participantId).samplesToIsolateDNA,
                      SampleStatus.RECEIVED)
    # only update dna sample will not update enrollmentStatusCoreStoredSampleTime
    self.assertEquals(
      self.dao.get(p_dna_samples.participantId).enrollmentStatusCoreStoredSampleTime, None)
    self.assertEquals(
      self.dao.get(p_dna_samples.participantId).enrollmentStatusCoreOrderedSampleTime, None)

  def test_calculate_enrollment_status(self):
    self.assertEquals(EnrollmentStatus.FULL_PARTICIPANT,
                      self.dao.calculate_enrollment_status(True,
                                                           NUM_BASELINE_PPI_MODULES,
                                                           PhysicalMeasurementsStatus.COMPLETED,
                                                           SampleStatus.RECEIVED))
    self.assertEquals(EnrollmentStatus.MEMBER,
                      self.dao.calculate_enrollment_status(True,
                                                           NUM_BASELINE_PPI_MODULES - 1,
                                                           PhysicalMeasurementsStatus.COMPLETED,
                                                           SampleStatus.RECEIVED))
    self.assertEquals(EnrollmentStatus.MEMBER,
                      self.dao.calculate_enrollment_status(True,
                                                           NUM_BASELINE_PPI_MODULES,
                                                           PhysicalMeasurementsStatus.UNSET,
                                                           SampleStatus.RECEIVED))
    self.assertEquals(EnrollmentStatus.MEMBER,
                      self.dao.calculate_enrollment_status(True,
                                                           NUM_BASELINE_PPI_MODULES,
                                                           PhysicalMeasurementsStatus.COMPLETED,
                                                           SampleStatus.UNSET))
    self.assertEquals(EnrollmentStatus.INTERESTED,
                      self.dao.calculate_enrollment_status(False,
                                                           NUM_BASELINE_PPI_MODULES,
                                                           PhysicalMeasurementsStatus.COMPLETED,
                                                           SampleStatus.RECEIVED))

  def testUpdateEnrollmentStatus(self):
    ehr_consent_time = datetime.datetime(2018, 3, 1)
    summary = ParticipantSummary(
        participantId=1,
        biobankId=2,
        consentForStudyEnrollment=QuestionnaireStatus.SUBMITTED,
        consentForElectronicHealthRecords=QuestionnaireStatus.SUBMITTED,
        consentForElectronicHealthRecordsTime=ehr_consent_time,
        enrollmentStatus=EnrollmentStatus.INTERESTED)
    self.dao.update_enrollment_status(summary)
    self.assertEquals(EnrollmentStatus.MEMBER, summary.enrollmentStatus)
    self.assertEquals(ehr_consent_time, summary.enrollmentStatusMemberTime)

  def testUpdateEnrollmentStatusLastModified(self):
    """DA-631: enrollment_status update should update last_modified."""
    participant = self._insert(Participant(participantId=6, biobankId=66))
    # collect current modified and enrollment status
    summary = self.dao.get(participant.participantId)
    test_dt = datetime.datetime(2018, 11, 1)

    def reset_summary():
      # change summary so enrollment status will be changed from INTERESTED to MEMBER.
      summary.enrollmentStatus = EnrollmentStatus.INTERESTED
      summary.lastModified = test_dt
      summary.consentForStudyEnrollment = QuestionnaireStatus.SUBMITTED
      summary.consentForElectronicHealthRecords = QuestionnaireStatus.SUBMITTED
      summary.physicalMeasurementsStatus = PhysicalMeasurementsStatus.COMPLETED
      summary.samplesToIsolateDNA = SampleStatus.RECEIVED
      self.dao.update(summary)

    ## Test Step 1: Validate update_from_biobank_stored_samples() changes lastModified.
    reset_summary()

    # Update and reload summary record
    self.dao.update_from_biobank_stored_samples(participant_id=participant.participantId)
    summary = self.dao.get(participant.participantId)

    # Test that status has changed and lastModified is also different
    self.assertEquals(EnrollmentStatus.MEMBER, summary.enrollmentStatus)
    self.assertNotEqual(test_dt, summary.lastModified)

    ## Test Step 2: Validate that update_enrollment_status() changes the lastModified property.
    reset_summary()
    summary = self.dao.get(participant.participantId)

    self.assertEqual(test_dt, summary.lastModified)

    # update_enrollment_status() does not touch the db, it only modifies object properties.
    self.dao.update_enrollment_status(summary)

    self.assertEquals(EnrollmentStatus.MEMBER, summary.enrollmentStatus)
    self.assertNotEqual(test_dt, summary.lastModified)

  def testNumberDistinctVisitsCounts(self):
    self.participant = self._insert(Participant(participantId=7, biobankId=77))
    # insert biobank order
    order = self.order_dao.insert(self._make_biobank_order())
    summary = self.dao.get(self.participant.participantId)
    self.assertEquals(summary.numberDistinctVisits, 1)
    cancel_request = cancel_biobank_order()
    # cancel biobank order
    self.order_dao.update_with_patch(order.biobankOrderId, cancel_request, order.version)
    summary = self.dao.get(self.participant.participantId)
    # distinct count should be 0
    self.assertEquals(summary.numberDistinctVisits, 0)

    self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                             TIME_1.isoformat()))
    # insert physical measurement
    measurement = self.measurement_dao.insert(self._make_physical_measurements())
    summary = self.dao.get(self.participant.participantId)
    # count should be 1
    self.assertEquals(summary.numberDistinctVisits, 1)

    # cancel the measurement
    cancel_measurement = get_restore_or_cancel_info()
    with self.measurement_dao.session() as session:
      self.measurement_dao.update_with_patch(measurement.physicalMeasurementsId, session,
                                             cancel_measurement)

    summary = self.dao.get(self.participant.participantId)
    # count should be 0
    self.assertEquals(summary.numberDistinctVisits, 0)

    with clock.FakeClock(TIME_1):
      self.order_dao.insert(self._make_biobank_order(biobankOrderId='2', identifiers=[
        BiobankOrderIdentifier(system='b', value='d')], samples=[BiobankOrderedSample(
                                                        biobankOrderId='2',
                                                        test=BIOBANK_TESTS[0],
                                                        description='description',
                                                        processingRequired=True)]))
    with clock.FakeClock(TIME_2):
      self.measurement_dao.insert(self._make_physical_measurements(
        physicalMeasurementsId=2))
      summary = self.dao.get(self.participant.participantId)

      # A PM on another day should add a new distinct count.
      self.assertEquals(summary.numberDistinctVisits, 2)

    with clock.FakeClock(TIME_3):
      self.order_dao.insert(self._make_biobank_order(biobankOrderId='3', identifiers=[
        BiobankOrderIdentifier(system='s', value='s')], samples=[BiobankOrderedSample(
        biobankOrderId ='3',
        finalized=TIME_3,
        test=BIOBANK_TESTS[1],
        description='another description',
        processingRequired=False)]))

      # a physical measurement on same day as biobank order does not add distinct visit.
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=6))

      # another biobank order on the same day should also not add a distinct visit
      self.order_dao.insert(self._make_biobank_order(biobankOrderId='7', identifiers=[
          BiobankOrderIdentifier(system='x', value='x')], samples=[BiobankOrderedSample(
              biobankOrderId ='7',
              finalized=TIME_3,
              test=BIOBANK_TESTS[1],
              description='another description',
              processingRequired=False)]))

      summary = self.dao.get(self.participant.participantId)
      # 1 from each of TIME_1 TIME_2 TIME_3
      self.assertEquals(summary.numberDistinctVisits, 3)


  def test_qa_scenarios_for_pmb_visits(self):
    """ PDR at https://docs.google.com/document/d/1sL54f-I91RvhjIprrdbwD8TlR9Jq91MX2ELf1EtJdxc/edit#heading=h.bqo8kt3igsrw<Paste> """
    self.participant = self._insert(Participant(participantId=6, biobankId=66))

    # test scenario 1
    with clock.FakeClock(TIME_4):
      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_4.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=666,
                                                                   participantId=self.participant.participantId,
                                                                   finalized=TIME_4))
      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

    with clock.FakeClock(TIME_5):
      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_5.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=669,
                                                                   finalized=TIME_5))
      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 2)

    # test scenario 2
    with clock.FakeClock(TIME_6):
      self.participant = self._insert(Participant(participantId=9, biobankId=13))
      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_6.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=8,
                                                                   finalized=TIME_6))
      self.order_dao.insert(self._make_biobank_order(biobankOrderId='2', identifiers=[
        BiobankOrderIdentifier(system='b', value='d')], samples=[BiobankOrderedSample(
                                                        biobankOrderId='2',
                                                        finalized=TIME_7,
                                                        test=BIOBANK_TESTS[0],
                                                        description='description',
                                                        processingRequired=True)]))


      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 2
      self.assertEquals(summary.numberDistinctVisits, 2)

    # test scenario 3
    with clock.FakeClock(TIME_6):
      self.participant = self._insert(Participant(participantId=66, biobankId=42))
      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_6.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=12,
                                                                   createdSiteId=2,
                                                                   finalized=TIME_6))

      self.order_dao.insert(self._make_biobank_order(biobankOrderId='18', finalizedSiteId=1, identifiers=[
          BiobankOrderIdentifier(system='x', value='y')], samples=[BiobankOrderedSample(
              biobankOrderId='18',
              finalized=TIME_6,
              test=BIOBANK_TESTS[0],
              description='description',
              processingRequired=True)]))


      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 1
      self.assertEquals(summary.numberDistinctVisits, 1)

    # test scenario 4
    with clock.FakeClock(TIME_8):
      self.participant = self._insert(Participant(participantId=6613, biobankId=142))
      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_8.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=129,
                                                                   finalized=TIME_8))

      order = self.order_dao.insert(self._make_biobank_order(biobankOrderId='999', identifiers=[
          BiobankOrderIdentifier(system='s', value='s')], samples=[BiobankOrderedSample(
              biobankOrderId='999',
              finalized=TIME_8,
              test=BIOBANK_TESTS[1],
              description='description',
              processingRequired=True)]))
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 1
      self.assertEquals(summary.numberDistinctVisits, 1)

     # change finalized time, recalculating count
      with self.order_dao.session() as session:
        existing_order = copy.deepcopy(order)
        order.samples[0].finalized = TIME_9
        self.order_dao._do_update(session, order, existing_order)

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

     # change test, should not change count.
      with self.order_dao.session() as session:
        existing_order = copy.deepcopy(order)
        order.samples[0].test = BIOBANK_TESTS[0]
        self.order_dao._do_update(session, order, existing_order)

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

    # test scenario 5
    with clock.FakeClock(TIME_12):
      self.participant = self._insert(Participant(participantId=3000, biobankId=2019))

      self.order_dao.insert(self._make_biobank_order(biobankOrderId='700', identifiers=[
          BiobankOrderIdentifier(system='n', value='s')], samples=[BiobankOrderedSample(
              biobankOrderId='700',
              finalized=TIME_10,
              test=BIOBANK_TESTS[1],
              description='description',
              processingRequired=True)]))
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 1
      self.assertEquals(summary.numberDistinctVisits, 1)

      other_order = self.order_dao.insert(self._make_biobank_order(biobankOrderId='701', identifiers=[
          BiobankOrderIdentifier(system='n', value='t')], samples=[BiobankOrderedSample(
              biobankOrderId='701',
              finalized=TIME_11,
              test=BIOBANK_TESTS[1],
              description='description',
              processingRequired=True)]))
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 2
      self.assertEquals(summary.numberDistinctVisits, 2)

      order = self.order_dao.insert(self._make_biobank_order(biobankOrderId='702', identifiers=[
          BiobankOrderIdentifier(system='n', value='u')], samples=[BiobankOrderedSample(
              biobankOrderId='702',
              finalized=TIME_12,
              test=BIOBANK_TESTS[1],
              description='description',
              processingRequired=True)]))
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 3
      self.assertEquals(summary.numberDistinctVisits, 3)

      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_12.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=120,
                                                                   finalized=TIME_12))

      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 3
      self.assertEquals(summary.numberDistinctVisits, 3)
      cancel_request = cancel_biobank_order()
      # cancel biobank order with PM on same day
      self.order_dao.update_with_patch(order.biobankOrderId, cancel_request, order.version)
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 3 (the PM on same day still counts)
      self.assertEquals(summary.numberDistinctVisits, 3)

      self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                               TIME_1.isoformat()))
      self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=150,
                                                                   finalized=TIME_1))
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 4
      self.assertEquals(summary.numberDistinctVisits, 4)
      # cancel order with pm on different day
      self.order_dao.update_with_patch(other_order.biobankOrderId, cancel_request, order.version)
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 3
      self.assertEquals(summary.numberDistinctVisits, 3)

  def test_pm_restore_cancel_biobank_restore_cancel(self):
    self.participant = self._insert(Participant(participantId=9, biobankId=13))
    self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                             TIME_4.isoformat()))
    measurement = self.measurement_dao.insert(self._make_physical_measurements(physicalMeasurementsId=669,
                                                                 finalized=TIME_4))
    summary = self.dao.get(self.participant.participantId)
    self.assertEquals(summary.numberDistinctVisits, 1)

    with clock.FakeClock(TIME_5):
      order = self.order_dao.insert(self._make_biobank_order(biobankOrderId='2', identifiers=[
        BiobankOrderIdentifier(system='b', value='d')], samples=[BiobankOrderedSample(
                                                        biobankOrderId='2',
                                                        finalized=TIME_5,
                                                        test=BIOBANK_TESTS[0],
                                                        description='description',
                                                        processingRequired=True)]))


    with clock.FakeClock(TIME_7):
      summary = self.dao.get(self.participant.participantId)
      # distinct count should be 2
      self.assertEquals(summary.numberDistinctVisits, 2)

      # cancel the measurement
      cancel_measurement = get_restore_or_cancel_info()
      with self.measurement_dao.session() as session:
        self.measurement_dao.update_with_patch(measurement.physicalMeasurementsId, session,
                                               cancel_measurement)

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

    with clock.FakeClock(TIME_7):
      restore_measurement = get_restore_or_cancel_info(status='restored')
      with self.measurement_dao.session() as session:
        self.measurement_dao.update_with_patch(measurement.physicalMeasurementsId, session,
                                               restore_measurement)

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 2)


      cancel_request = cancel_biobank_order()
      order = self.order_dao.update_with_patch(order.biobankOrderId, cancel_request, order.version)

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

      restore_order = get_restore_or_cancel_info(status='restored')
      restore_order['amendedReason'] = 'some reason'
      self.order_dao.update_with_patch(order.biobankOrderId, restore_order, order.version)
      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 2)

  def test_amending_biobank_order_distinct_visit_count(self):
    self.participant = self._insert(Participant(participantId=9, biobankId=13))
    with clock.FakeClock(TIME_5):
      order = self.order_dao.insert(self._make_biobank_order(biobankOrderId='2', identifiers=[
        BiobankOrderIdentifier(system='b', value='d')], samples=[BiobankOrderedSample(
                                                        biobankOrderId='2',
                                                        finalized=TIME_5,
                                                        test=BIOBANK_TESTS[0],
                                                        description='description',
                                                        processingRequired=True)]))

      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

    with clock.FakeClock(TIME_7):
      amend_order = self._get_amended_info(order)
      with self.order_dao.session() as session:
        self.order_dao._do_update(session, amend_order, order)

      # Shouldn't change on a simple amendment (unless finalized time on samples change)
      summary = self.dao.get(self.participant.participantId)
      self.assertEquals(summary.numberDistinctVisits, 1)

    with clock.FakeClock(TIME_7_5):
      cancel_request = cancel_biobank_order()
      order = self.order_dao.update_with_patch(order.biobankOrderId, cancel_request, order.version)

    # A cancelled order (even after amending) should reduce count (unless some other valid order on same day)
    summary = self.dao.get(self.participant.participantId)
    self.assertEquals(summary.numberDistinctVisits, 0)

  @staticmethod
  def _get_amended_info(order):
    amendment = dict(amendedReason='I had to change something', amendedInfo={
      "author": {
        "system": "https://www.pmi-ops.org/healthpro-username",
        "value": "*****@*****.**"
      },
      "site": {
        "system": "https://www.pmi-ops.org/site-id",
        "value": "hpo-site-monroeville"
      }
    })

    order.amendedReason = amendment['amendedReason']
    order.amendedInfo = amendment['amendedInfo']
    return order



  def _make_biobank_order(self, **kwargs):
    """Makes a new BiobankOrder (same values every time) with valid/complete defaults.

    Kwargs pass through to BiobankOrder constructor, overriding defaults.
    """
    for k, default_value in (
        ('biobankOrderId', '1'),
        ('created', clock.CLOCK.now()),
        ('participantId', self.participant.participantId),
        ('sourceSiteId', 1),
        ('sourceUsername', '*****@*****.**'),
        ('collectedSiteId', 1),
        ('collectedUsername', '*****@*****.**'),
        ('processedSiteId', 1),
        ('processedUsername', '*****@*****.**'),
        ('finalizedSiteId', 2),
        ('finalizedUsername', '*****@*****.**'),
        ('identifiers', [BiobankOrderIdentifier(system='a', value='c')]),
        ('samples', [BiobankOrderedSample(
            biobankOrderId='1',
            test=BIOBANK_TESTS[0],
            description='description',
            finalized=TIME_1,
            processingRequired=True)])):
      if k not in kwargs:
        kwargs[k] = default_value
    return BiobankOrder(**kwargs)

  def _make_physical_measurements(self, **kwargs):
    """Makes a new PhysicalMeasurements (same values every time) with valid/complete defaults.

    Kwargs pass through to PM constructor, overriding defaults.
    """
    for k, default_value in (
        ('physicalMeasurementsId', 1),
        ('participantId', self.participant.participantId),
        ('resource', self.measurement_json),
        ('createdSiteId', 1),
        ('finalized', TIME_3),
        ('finalizedSiteId', 2)):
      if k not in kwargs:
        kwargs[k] = default_value
    return PhysicalMeasurements(**kwargs)
Example #9
0
 def test_from_client_json(self):
   measurement = PhysicalMeasurementsDao.from_client_json(json.loads(self.measurement_json))
   self.assertIsNotNone(measurement.createdSiteId)
   self.assertIsNotNone(measurement.finalizedSiteId)
Example #10
0
class PhysicalMeasurementsDaoTest(SqlTestBase):
  def setUp(self):
    super(PhysicalMeasurementsDaoTest, self).setUp()
    self.participant = Participant(participantId=1, biobankId=2)
    ParticipantDao().insert(self.participant)
    self.dao = PhysicalMeasurementsDao()
    self.participant_summary_dao = ParticipantSummaryDao()
    self.measurement_json = json.dumps(load_measurement_json(self.participant.participantId,
                                                             TIME_1.isoformat()))
    self.biobank = BiobankOrderDao()

  def test_from_client_json(self):
    measurement = PhysicalMeasurementsDao.from_client_json(json.loads(self.measurement_json))
    self.assertIsNotNone(measurement.createdSiteId)
    self.assertIsNotNone(measurement.finalizedSiteId)

  def _make_physical_measurements(self, **kwargs):
    """Makes a new PhysicalMeasurements (same values every time) with valid/complete defaults.

    Kwargs pass through to PM constructor, overriding defaults.
    """
    for k, default_value in (
        ('physicalMeasurementsId', 1),
        ('participantId', self.participant.participantId),
        ('resource', self.measurement_json),
        ('createdSiteId', 1),
        ('finalizedSiteId', 2)):
      if k not in kwargs:
        kwargs[k] = default_value
    return PhysicalMeasurements(**kwargs)

  def testInsert_noParticipantId(self):
    with self.assertRaises(BadRequest):
      self.dao.insert(self._make_physical_measurements(participantId=None))

  def testInsert_wrongParticipantId(self):
    with self.assertRaises(BadRequest):
      self.dao.insert(self._make_physical_measurements(participantId=2))

  def _with_id(self, resource, id_):
    measurements_json = json.loads(resource)
    measurements_json['id'] = id_
    return json.dumps(measurements_json)

  def testInsert_noSummary(self):
    with self.assertRaises(BadRequest):
      self.dao.insert(self._make_physical_measurements())

  def _make_summary(self):
    self.participant_summary_dao.insert(self.participant_summary(self.participant))

  def testInsert_rightParticipantId(self):
    self._make_summary()
    summary = ParticipantSummaryDao().get(self.participant.participantId)
    self.assertIsNone(summary.physicalMeasurementsStatus)
    with FakeClock(TIME_2):
      measurements = self.dao.insert(self._make_physical_measurements())

    expected_measurements = PhysicalMeasurements(
        physicalMeasurementsId=1,
        participantId=self.participant.participantId,
        resource=self._with_id(self.measurement_json, '1'),
        created=TIME_2,
        finalized=TIME_1,
        final=True,
        logPositionId=1,
        createdSiteId=1,
        finalizedSiteId=2)
    self.assertEquals(expected_measurements.asdict(), measurements.asdict())
    measurements = self.dao.get(measurements.physicalMeasurementsId)
    self.assertEquals(expected_measurements.asdict(), measurements.asdict())
    # Completing physical measurements changes the participant summary status
    summary = ParticipantSummaryDao().get(self.participant.participantId)
    self.assertEquals(PhysicalMeasurementsStatus.COMPLETED, summary.physicalMeasurementsStatus)
    self.assertEquals(TIME_2, summary.physicalMeasurementsTime)
    self.assertEquals(TIME_2, summary.lastModified)

  def test_backfill_is_noop(self):
    self._make_summary()
    measurements_id = self.dao.insert(self._make_physical_measurements()).physicalMeasurementsId
    orig_measurements = self.dao.get_with_children(measurements_id).asdict()
    self.dao.backfill_measurements()
    backfilled_measurements = self.dao.get_with_children(measurements_id).asdict()
    # Formatting of resource gets changed, so test it separately as parsed JSON.
    self.assertEquals(
        json.loads(orig_measurements['resource']),
        json.loads(backfilled_measurements['resource']))
    del orig_measurements['resource']
    del backfilled_measurements['resource']
    self.assertEquals(orig_measurements, backfilled_measurements)

  def testInsert_withdrawnParticipantFails(self):
    self.participant.withdrawalStatus = WithdrawalStatus.NO_USE
    ParticipantDao().update(self.participant)
    self._make_summary()
    summary = ParticipantSummaryDao().get(self.participant.participantId)
    self.assertIsNone(summary.physicalMeasurementsStatus)
    with self.assertRaises(Forbidden):
      self.dao.insert(self._make_physical_measurements())

  def testInsert_getFailsForWithdrawnParticipant(self):
    self._make_summary()
    self.dao.insert(self._make_physical_measurements())
    self.participant.version += 1
    self.participant.withdrawalStatus = WithdrawalStatus.NO_USE
    ParticipantDao().update(self.participant)
    with self.assertRaises(Forbidden):
      self.dao.get(1)
    with self.assertRaises(Forbidden):
      self.dao.query(Query([FieldFilter('participantId', Operator.EQUALS,
                                        self.participant.participantId)],
                           None, 10, None))

  def testInsert_duplicate(self):
    self._make_summary()
    with FakeClock(TIME_2):
      measurements = self.dao.insert(self._make_physical_measurements())
    with FakeClock(TIME_3):
      measurements_2 = self.dao.insert(self._make_physical_measurements())
    self.assertEquals(measurements.asdict(), measurements_2.asdict())

  def testInsert_amend(self):
    self._make_summary()
    with FakeClock(TIME_2):
      measurements = self.dao.insert(self._make_physical_measurements(
          physicalMeasurementsId=1))

    amendment_json = load_measurement_json_amendment(self.participant.participantId,
                                                     measurements.physicalMeasurementsId,
                                                     TIME_2)
    with FakeClock(TIME_3):
      new_measurements = self.dao.insert(self._make_physical_measurements(
          physicalMeasurementsId=2, resource=json.dumps(amendment_json)))

    measurements = self.dao.get(measurements.physicalMeasurementsId)
    amended_json = json.loads(measurements.resource)
    self.assertEquals('amended', amended_json['entry'][0]['resource']['status'])
    self.assertEquals('1', amended_json['id'])

    amendment_json = json.loads(new_measurements.resource)
    self.assertEquals('2', amendment_json['id'])
    self.assertTrue(new_measurements.final)
    self.assertEquals(TIME_3, new_measurements.created)
def sync_physical_measurements():
    max_results = config.getSetting(config.MEASUREMENTS_ENTITIES_PER_SYNC, 100)
    return get_sync_results_for_request(PhysicalMeasurementsDao(), max_results)
 def __init__(self):
     super(PhysicalMeasurementsApi,
           self).__init__(PhysicalMeasurementsDao())
Example #13
0
def main(args):
  if args.run_backfill:
    num_updated = PhysicalMeasurementsDao().backfill_measurements()
    logging.info("%d measurements updated." % num_updated)
  else:
    pprint(PhysicalMeasurementsDao().get_distinct_measurements_json(), indent=2)