Exemplo n.º 1
0
 def to_client_json(self, model):
   client_json = {
     'participantId': to_client_participant_id(model.participantId),
     'externalId': model.externalId,
     'hpoId': model.hpoId,
     'awardee': model.hpoId,
     'organization': model.organizationId,
     'siteId': model.siteId,
     'biobankId': to_client_biobank_id(model.biobankId),
     'lastModified': model.lastModified.isoformat(),
     'signUpTime': model.signUpTime.isoformat(),
     'providerLink': json.loads(model.providerLink),
     'withdrawalStatus': model.withdrawalStatus,
     'withdrawalReason': model.withdrawalReason,
     'withdrawalReasonJustification': model.withdrawalReasonJustification,
     'withdrawalTime': model.withdrawalTime,
     'withdrawalAuthored': model.withdrawalAuthored,
     'suspensionStatus': model.suspensionStatus,
     'suspensionTime': model.suspensionTime
   }
   format_json_hpo(client_json, self.hpo_dao, 'hpoId'),
   format_json_org(client_json, self.organization_dao, 'organization'),
   format_json_site(client_json, self.site_dao, 'site'),
   format_json_enum(client_json, 'withdrawalStatus')
   format_json_enum(client_json, 'withdrawalReason')
   format_json_enum(client_json, 'suspensionStatus')
   format_json_date(client_json, 'withdrawalTime')
   format_json_date(client_json, 'suspensionTime')
   client_json['awardee'] = client_json['hpoId']
   if 'siteId' in client_json:
     del client_json['siteId']
   return client_json
Exemplo n.º 2
0
def load_questionnaire_response_with_consents(questionnaire_id, participant_id,
                                              first_name_link_id,
                                              last_name_link_id,
                                              email_address_link_id,
                                              consent_pdf_paths):
    """Loads a consent QuestionnaireResponse and adds >= 1 consent PDF extensions."""
    # PDF paths are expected to be something like "/Participant/P550613540/ConsentPII__8270.pdf".
    assert len(consent_pdf_paths) >= 1
    with open(data_path('questionnaire_response_consent.json')) as f:
        resource = json.loads(
            f.read() % {
                'questionnaire_id': questionnaire_id,
                'participant_client_id':
                to_client_participant_id(participant_id),
                'first_name_link_id': first_name_link_id,
                'last_name_link_id': last_name_link_id,
                'email_address_link_id': email_address_link_id,
            })
    for path in consent_pdf_paths:
        resource['extension'].append({
            'url':
            'http://terminology.pmi-ops.org/StructureDefinition/consent-form-signed-pdf',
            'valueString': path,
        })
    return resource
Exemplo n.º 3
0
 def _make_bundle(self, results, id_field, participant_id):
     import main
     bundle_dict = {"resourceType": "Bundle", "type": "searchset"}
     if results.pagination_token:
         query_params = request.args.copy()
         query_params['_token'] = results.pagination_token
         next_url = main.api.url_for(self.__class__,
                                     _external=True,
                                     **query_params)
         bundle_dict['link'] = [{"relation": "next", "url": next_url}]
     entries = []
     for item in results.items:
         json = self.dao.to_client_json(item)
         if participant_id:
             full_url = main.api.url_for(
                 self.__class__,
                 id_=json[id_field],
                 p_id=to_client_participant_id(participant_id),
                 _external=True)
         else:
             full_url = main.api.url_for(self.__class__,
                                         p_id=json[id_field],
                                         _external=True)
         entries.append({"fullUrl": full_url, "resource": json})
     bundle_dict['entry'] = entries
     return bundle_dict
    def test_validation_no_answer(self):
        self.participant = Participant(participantId=123, biobankId=555)
        ParticipantDao().insert(self.participant)
        self.participant_id = to_client_participant_id(
            self.participant.participantId)
        summary = ParticipantSummaryDao().insert(
            self.participant_summary(self.participant))

        result = check_ppi_data_api._get_validation_result(
            summary.email, {FIRST_NAME_QUESTION_CODE: 'NotAnswered'})
        self.assertEquals(1, result.tests_count)
        self.assertEquals(1, result.errors_count)
        self.assertEquals(1, len(result.messages))
        self.assertIn(FIRST_NAME_QUESTION_CODE, result.messages[0])

        # test using phone number as lookup value in API.
        summary.loginPhoneNumber = '5555555555'
        ParticipantSummaryDao().update(summary)
        result = check_ppi_data_api._get_validation_result(
            summary.loginPhoneNumber,
            {FIRST_NAME_QUESTION_CODE: 'NotAnswered'})
        self.assertEquals(1, result.tests_count)
        self.assertEquals(1, result.errors_count)
        self.assertEquals(1, len(result.messages))
        self.assertIn(FIRST_NAME_QUESTION_CODE, result.messages[0])
    def to_client_json(self, model):
        result = model.asdict()
        # Participants that withdrew more than 48 hours ago should have fields other than
        # WITHDRAWN_PARTICIPANT_FIELDS cleared.
        if (model.withdrawalStatus == WithdrawalStatus.NO_USE
                and model.withdrawalTime <
                clock.CLOCK.now() - WITHDRAWN_PARTICIPANT_VISIBILITY_TIME):
            result = {k: result.get(k) for k in WITHDRAWN_PARTICIPANT_FIELDS}

        result['participantId'] = to_client_participant_id(model.participantId)
        biobank_id = result.get('biobankId')
        if biobank_id:
            result['biobankId'] = to_client_biobank_id(biobank_id)
        date_of_birth = result.get('dateOfBirth')
        if date_of_birth:
            result['ageRange'] = get_bucketed_age(date_of_birth,
                                                  clock.CLOCK.now())
        else:
            result['ageRange'] = UNSET
        format_json_hpo(result, self.hpo_dao, 'hpoId')
        _initialize_field_type_sets()
        for fieldname in _DATE_FIELDS:
            format_json_date(result, fieldname)
        for fieldname in _CODE_FIELDS:
            format_json_code(result, self.code_dao, fieldname)
        for fieldname in _ENUM_FIELDS:
            format_json_enum(result, fieldname)
        if (model.withdrawalStatus == WithdrawalStatus.NO_USE
                or model.suspensionStatus == SuspensionStatus.NO_CONTACT):
            result['recontactMethod'] = 'NO_CONTACT'
        # Strip None values.
        result = {k: v for k, v in result.iteritems() if v is not None}

        return result
Exemplo n.º 6
0
  def test_not_pairing_at_pm_when_has_bio(self):
    self.participant_id = self.create_participant()
    _id = int(self.participant_id[1:])
    self.path = (
      'Participant/%s/BiobankOrder' % to_client_participant_id(_id))
    pid_numeric = from_client_participant_id(self.participant_id)
    self.send_consent(self.participant_id)
    self.send_post(self.path, load_biobank_order_json(pid_numeric))
    participant_paired = self.summary_dao.get(pid_numeric)

    self.assertEqual(participant_paired.siteId, participant_paired.biospecimenCollectedSiteId)
    self.path = (
      'Participant/%s/PhysicalMeasurements' % to_client_participant_id(pid_numeric))
    self._insert_measurements(datetime.datetime.utcnow().isoformat())
    self.assertNotEqual(participant_paired.siteId,
                        participant_paired.physicalMeasurementsFinalizedSiteId)
Exemplo n.º 7
0
def load_biobank_order_json(participant_id, filename='biobank_order_1.json'):
    with open(data_path(filename)) as f:
        return json.loads(
            f.read() % {
                'participant_id': participant_id,
                'client_participant_id':
                to_client_participant_id(participant_id),
            })
Exemplo n.º 8
0
 def setUp(self):
     super(BiobankOrderApiTest, self).setUp()
     self.participant = Participant(participantId=123, biobankId=555)
     self.participant_dao = ParticipantDao()
     self.participant_dao.insert(self.participant)
     self.summary_dao = ParticipantSummaryDao()
     self.path = ('Participant/%s/BiobankOrder' %
                  to_client_participant_id(self.participant.participantId))
Exemplo n.º 9
0
    def _insert_participant(self, race_codes=[]):
        participant = self.participant_dao.insert(Participant())
        # satisfies the consent requirement
        self.summary_dao.insert(self.participant_summary(participant))

        if race_codes:
            self._submit_race_questionnaire_response(
                to_client_participant_id(participant.participantId),
                race_codes)
        return participant
Exemplo n.º 10
0
 def _make_resource_url(self, json, id_field, participant_id):
   import main
   if participant_id:
     return main.api.url_for(self.__class__,
                             id_=json[id_field],
                             p_id=to_client_participant_id(participant_id),
                             _external=True)
   else:
     return main.api.url_for(self.__class__, p_id=json[id_field],
                             _external=True)
Exemplo n.º 11
0
    def test_bio_after_cancelled_pm(self):
        self.participant_id = self.create_participant()
        self.send_consent(self.participant_id)
        measurement = load_measurement_json(self.participant_id)
        measurement2 = load_measurement_json(self.participant_id)

        # send both PM's
        pm_path = 'Participant/%s/PhysicalMeasurements' % self.participant_id
        response = self.send_post(pm_path, measurement)
        self.send_post(pm_path, measurement2)

        # cancel the 1st PM
        pm_path = pm_path + '/' + response['id']
        cancel_info = get_restore_or_cancel_info()
        self.send_patch(pm_path, cancel_info)

        # set up questionnaires to hit the calculate_max_core_sample_time in participant summary
        questionnaire_id = self.create_questionnaire('questionnaire3.json')
        questionnaire_id_1 = self.create_questionnaire(
            'all_consents_questionnaire.json')
        questionnaire_id_2 = self.create_questionnaire('questionnaire4.json')
        self._submit_consent_questionnaire_response(
            self.participant_id,
            questionnaire_id_1,
            CONSENT_PERMISSION_YES_CODE,
            time=TIME_6)

        self.submit_questionnaire_response(self.participant_id,
                                           questionnaire_id,
                                           RACE_NONE_OF_THESE_CODE, None, None,
                                           datetime.date(1978, 10, 10))

        self._submit_empty_questionnaire_response(self.participant_id,
                                                  questionnaire_id_2)

        # send a biobank order
        _id = int(self.participant_id[1:])
        self.path = ('Participant/%s/BiobankOrder' %
                     to_client_participant_id(_id))
        pid_numeric = from_client_participant_id(self.participant_id)
        self.send_post(self.path, load_biobank_order_json(pid_numeric))

        # fetch participant summary
        ps = self.send_get('ParticipantSummary?participantId=%s' % _id)

        self.assertTrue(
            ps['entry'][0]['resource']["physicalMeasurementsFinalizedTime"])
        self.assertEquals(
            ps['entry'][0]['resource']["physicalMeasurementsFinalizedSite"],
            'hpo-site-bannerphoenix')
        self.assertIsNotNone('biobankId', ps['entry'][0]['resource'])
Exemplo n.º 12
0
 def to_client_json(self, model):
   client_json = {
       'participantId': to_client_participant_id(model.participantId),
       'biobankId': to_client_biobank_id(model.biobankId),
       'lastModified': model.lastModified.isoformat(),
       'signUpTime': model.signUpTime.isoformat(),
       'providerLink': json.loads(model.providerLink),
       'withdrawalStatus': model.withdrawalStatus,
       'withdrawalTime': model.withdrawalTime,
       'suspensionStatus': model.suspensionStatus,
       'suspensionTime': model.suspensionTime
   }
   format_json_enum(client_json, 'withdrawalStatus')
   format_json_enum(client_json, 'suspensionStatus')
   format_json_date(client_json, 'withdrawalTime')
   format_json_date(client_json, 'suspensionTime')
   return client_json
    def to_client_json(self, model, for_update=False):
        if for_update:
            result = dict()
            reduced_model = model['orders']['order']
            result['biobankStatus'] = reduced_model['status']
            result['barcode'] = reduced_model['reference_number']
            result['received'] = reduced_model['received']
            result['biobankOrderId'] = reduced_model['number']
            result['biobankTrackingId'] = reduced_model['patient'][
                'medical_record_number']
        else:
            result = model.asdict()
            result['orderStatus'] = format_json_enum(result, 'orderStatus')
            result['shipmentStatus'] = format_json_enum(
                result, 'shipmentStatus')
            format_json_code(result, self.code_dao, 'stateId')
            result['state'] = result['state'][-2:]  # Get the abbreviation
            del result['id']  # PK for model

        result = {k: v for k, v in result.items() if v is not None}
        if 'participantId' in result:
            result['participantId'] = to_client_participant_id(
                result['participantId'])
        return result
Exemplo n.º 14
0
 def _participant_id_to_subject(cls, participant_id):
     return 'Patient/%s' % to_client_participant_id(participant_id)
Exemplo n.º 15
0
    def test_reconciliation_query(self):
        self.setup_codes([RACE_QUESTION_CODE], CodeType.QUESTION)
        self.setup_codes([RACE_AIAN_CODE, RACE_WHITE_CODE], CodeType.ANSWER)
        self._questionnaire_id = self.create_questionnaire(
            'questionnaire3.json')
        # MySQL and Python sub-second rounding differs, so trim micros from generated times.
        order_time = clock.CLOCK.now().replace(microsecond=0)
        old_order_time = order_time - datetime.timedelta(days=10)
        within_24_hours = order_time + datetime.timedelta(hours=23)
        old_within_24_hours = old_order_time + datetime.timedelta(hours=23)
        late_time = order_time + datetime.timedelta(hours=25)
        old_late_time = old_order_time + datetime.timedelta(hours=25)
        file_time = order_time + datetime.timedelta(
            hours=23) + datetime.timedelta(minutes=59)
        two_days_ago = file_time - datetime.timedelta(days=2)

        # On time, recent order and samples; shows up in rx
        p_on_time = self._insert_participant()
        # Extra samples ordered now aren't considered missing or late.
        self._insert_order(p_on_time,
                           'GoodOrder',
                           BIOBANK_TESTS[:4],
                           order_time,
                           finalized_tests=BIOBANK_TESTS[:3],
                           kit_id='kit1',
                           tracking_number='t1')
        self._insert_samples(p_on_time, BIOBANK_TESTS[:2],
                             ['GoodSample1', 'GoodSample2'], within_24_hours,
                             within_24_hours - datetime.timedelta(hours=1))

        # On time order and samples from 10 days ago; shows up in rx
        p_old_on_time = self._insert_participant(race_codes=[RACE_AIAN_CODE])
        # Old missing samples from 10 days ago don't show up in missing or late.
        self._insert_order(p_old_on_time,
                           'OldGoodOrder',
                           BIOBANK_TESTS[:3],
                           old_order_time,
                           kit_id='kit2')
        self._insert_samples(p_old_on_time, BIOBANK_TESTS[:2],
                             ['OldGoodSample1', 'OldGoodSample2'],
                             old_within_24_hours,
                             old_within_24_hours - datetime.timedelta(hours=1))

        # Late, recent order and samples; shows up in rx and late. (But not missing, as it hasn't been
        # 24 hours since the order.)
        p_late_and_missing = self._insert_participant()
        # Extra missing sample doesn't show up as missing as it hasn't been 24 hours yet.
        o_late_and_missing = self._insert_order(p_late_and_missing,
                                                'SlowOrder', BIOBANK_TESTS[:3],
                                                order_time)
        self._insert_samples(p_late_and_missing, [BIOBANK_TESTS[0]],
                             ['LateSample'], late_time,
                             late_time - datetime.timedelta(minutes=59))

        # Late order and samples from 10 days ago; shows up in rx (but not missing, as it was too
        # long ago.
        p_old_late_and_missing = self._insert_participant()
        self._insert_order(p_old_late_and_missing, 'OldSlowOrder',
                           BIOBANK_TESTS[:2], old_order_time)
        self._insert_samples(p_old_late_and_missing, [BIOBANK_TESTS[0]],
                             ['OldLateSample'], old_late_time,
                             old_late_time - datetime.timedelta(minutes=59))

        # Order with missing sample from 2 days ago; shows up in rx and missing.
        p_two_days_missing = self._insert_participant()
        # The third test doesn't wind up in missing, as it was never finalized.
        self._insert_order(p_two_days_missing,
                           'TwoDaysMissingOrder',
                           BIOBANK_TESTS[:3],
                           two_days_ago,
                           finalized_tests=BIOBANK_TESTS[:2])

        # Recent samples with no matching order; shows up in missing.
        p_extra = self._insert_participant(race_codes=[RACE_WHITE_CODE])
        self._insert_samples(p_extra, [BIOBANK_TESTS[-1]],
                             ['NobodyOrderedThisSample'], order_time,
                             order_time - datetime.timedelta(minutes=59))

        # Old samples with no matching order; shows up in rx.
        p_old_extra = self._insert_participant(race_codes=[RACE_AIAN_CODE])
        self._insert_samples(p_old_extra, [BIOBANK_TESTS[-1]],
                             ['OldNobodyOrderedThisSample'], old_order_time,
                             old_order_time - datetime.timedelta(hours=1))

        # Withdrawn participants don't show up in any reports except withdrawal report.

        p_withdrawn_old_on_time = self._insert_participant(
            race_codes=[RACE_AIAN_CODE])
        # This updates the version of the participant and its HPO ID.
        self._insert_order(p_withdrawn_old_on_time, 'OldWithdrawnGoodOrder',
                           BIOBANK_TESTS[:2], old_order_time)
        p_withdrawn_old_on_time = self.participant_dao.get(
            p_withdrawn_old_on_time.participantId)
        self._insert_samples(
            p_withdrawn_old_on_time, BIOBANK_TESTS[:2],
            ['OldWithdrawnGoodSample1', 'OldWithdrawnGoodSample2'],
            old_within_24_hours,
            old_within_24_hours - datetime.timedelta(hours=1))
        self._withdraw(p_withdrawn_old_on_time, within_24_hours)

        p_withdrawn_late_and_missing = self._insert_participant()
        self._insert_order(p_withdrawn_late_and_missing, 'WithdrawnSlowOrder',
                           BIOBANK_TESTS[:2], order_time)
        self._insert_samples(p_withdrawn_late_and_missing, [BIOBANK_TESTS[0]],
                             ['WithdrawnLateSample'], late_time,
                             late_time - datetime.timedelta(minutes=59))
        p_withdrawn_late_and_missing = (self.participant_dao.get(
            p_withdrawn_late_and_missing.participantId))
        self._withdraw(p_withdrawn_late_and_missing, within_24_hours)

        p_withdrawn_old_late_and_missing = self._insert_participant()
        self._insert_order(p_withdrawn_old_late_and_missing,
                           'WithdrawnOldSlowOrder', BIOBANK_TESTS[:2],
                           old_order_time)
        self._insert_samples(p_withdrawn_old_late_and_missing,
                             [BIOBANK_TESTS[0]], ['WithdrawnOldLateSample'],
                             old_late_time,
                             old_late_time - datetime.timedelta(minutes=59))
        p_withdrawn_old_late_and_missing = (self.participant_dao.get(
            p_withdrawn_old_late_and_missing.participantId))
        self._withdraw(p_withdrawn_old_late_and_missing, old_late_time)

        p_withdrawn_extra = self._insert_participant(
            race_codes=[RACE_WHITE_CODE])
        self._insert_samples(p_withdrawn_extra, [BIOBANK_TESTS[-1]],
                             ['WithdrawnNobodyOrderedThisSample'], order_time,
                             order_time - datetime.timedelta(hours=1))
        self._withdraw(p_withdrawn_extra, within_24_hours)

        p_withdrawn_old_extra = self._insert_participant(
            race_codes=[RACE_AIAN_CODE])
        self._insert_samples(p_withdrawn_old_extra, [BIOBANK_TESTS[-1]],
                             ['WithdrawnOldNobodyOrderedThisSample'],
                             old_order_time,
                             old_order_time - datetime.timedelta(hours=1))
        self._withdraw(p_withdrawn_old_extra, within_24_hours)

        p_withdrawn_race_change = self._insert_participant(
            race_codes=[RACE_AIAN_CODE])
        p_withdrawn_race_change_id = to_client_participant_id(
            p_withdrawn_race_change.participantId)
        self._submit_race_questionnaire_response(p_withdrawn_race_change_id,
                                                 [RACE_WHITE_CODE])
        self._withdraw(p_withdrawn_race_change, within_24_hours)

        # for the same participant/test, 3 orders sent and only 2 samples received. Shows up in both
        # missing (we are missing one sample) and late (the two samples that were received were after
        # 24 hours.)
        p_repeated = self._insert_participant()
        for repetition in xrange(3):
            self._insert_order(
                p_repeated, 'RepeatedOrder%d' % repetition, [BIOBANK_TESTS[0]],
                two_days_ago + datetime.timedelta(hours=repetition))
            if repetition != 2:
                self._insert_samples(
                    p_repeated, [BIOBANK_TESTS[0]],
                    ['RepeatedSample%d' % repetition],
                    within_24_hours + datetime.timedelta(hours=repetition),
                    within_24_hours + datetime.timedelta(hours=repetition - 1))

        received, late, missing, withdrawals = 'rx.csv', 'late.csv', 'missing.csv', 'withdrawals.csv'
        exporter = InMemorySqlExporter(self)
        biobank_samples_pipeline._query_and_write_reports(
            exporter, file_time, received, late, missing, withdrawals)

        exporter.assertFilesEqual((received, late, missing, withdrawals))

        # sent-and-received: 4 on-time, 2 late, none of the missing/extra/repeated ones;
        # includes orders/samples from more than 7 days ago
        exporter.assertRowCount(received, 6)
        exporter.assertColumnNamesEqual(received, _CSV_COLUMN_NAMES)
        row = exporter.assertHasRow(
            received, {
                'biobank_id': to_client_biobank_id(p_on_time.biobankId),
                'sent_test': BIOBANK_TESTS[0],
                'received_test': BIOBANK_TESTS[0]
            })
        # Also check the values of all remaining fields on one row.
        self.assertEquals(row['source_site_name'],
                          'Monroeville Urgent Care Center')
        self.assertEquals(row['source_site_consortium'], 'Pittsburgh')
        self.assertEquals(row['source_site_mayolink_client_number'], '7035769')
        self.assertEquals(row['source_site_hpo'], 'PITT')
        self.assertEquals(row['source_site_hpo_type'], 'HPO')
        self.assertEquals(row['finalized_site_name'],
                          'Monroeville Urgent Care Center')
        self.assertEquals(row['finalized_site_consortium'], 'Pittsburgh')
        self.assertEquals(row['finalized_site_mayolink_client_number'],
                          '7035769')
        self.assertEquals(row['finalized_site_hpo'], 'PITT')
        self.assertEquals(row['finalized_site_hpo_type'], 'HPO')
        self.assertEquals(row['finalized_username'], '*****@*****.**')
        self.assertEquals(row['sent_finalized_time'],
                          database_utils.format_datetime(order_time))
        self.assertEquals(row['sent_collection_time'],
                          database_utils.format_datetime(order_time))
        self.assertEquals(row['sent_processed_time'],
                          database_utils.format_datetime(order_time))
        self.assertEquals(row['received_time'],
                          database_utils.format_datetime(within_24_hours))
        self.assertEquals(
            row['Sample Family Create Date'],
            database_utils.format_datetime(within_24_hours -
                                           datetime.timedelta(hours=1)))
        self.assertEquals(row['sent_count'], '1')
        self.assertEquals(row['received_count'], '1')
        self.assertEquals(row['sent_order_id'], 'OGoodOrder')
        self.assertEquals(row['received_sample_id'], 'GoodSample1')
        self.assertEquals(row['biospecimen_kit_id'], 'kit1')
        self.assertEquals(row['fedex_tracking_number'], 't1')
        # the other sent-and-received rows
        exporter.assertHasRow(
            received, {
                'biobank_id': to_client_biobank_id(p_on_time.biobankId),
                'sent_test': BIOBANK_TESTS[1]
            })
        exporter.assertHasRow(
            received, {
                'biobank_id': to_client_biobank_id(
                    p_late_and_missing.biobankId),
                'sent_test': BIOBANK_TESTS[0]
            })
        exporter.assertHasRow(
            received, {
                'biobank_id': to_client_biobank_id(p_old_on_time.biobankId),
                'sent_test': BIOBANK_TESTS[0]
            })
        exporter.assertHasRow(
            received, {
                'biobank_id': to_client_biobank_id(p_old_on_time.biobankId),
                'sent_test': BIOBANK_TESTS[1]
            })
        exporter.assertHasRow(
            received, {
                'biobank_id':
                to_client_biobank_id(p_old_late_and_missing.biobankId),
                'sent_test':
                BIOBANK_TESTS[0]
            })

        # sent-and-received: 2 late; don't include orders/samples from more than 7 days ago
        exporter.assertRowCount(late, 2)
        exporter.assertColumnNamesEqual(late, _CSV_COLUMN_NAMES)
        exporter.assertHasRow(
            late, {
                'biobank_id': to_client_biobank_id(
                    p_late_and_missing.biobankId),
                'sent_order_id': 'O%s' % o_late_and_missing.biobankOrderId,
                'elapsed_hours': '24'
            })
        exporter.assertHasRow(
            late, {
                'biobank_id': to_client_biobank_id(p_repeated.biobankId),
                'elapsed_hours': '45'
            })

        # orders/samples where something went wrong; don't include orders/samples from more than 7
        # days ago, or where 24 hours hasn't elapsed yet.
        exporter.assertRowCount(missing, 4)
        exporter.assertColumnNamesEqual(missing, _CSV_COLUMN_NAMES)
        # sample received, nothing ordered
        exporter.assertHasRow(
            missing, {
                'biobank_id': to_client_biobank_id(p_extra.biobankId),
                'sent_order_id': ''
            })
        # order received, no sample
        exporter.assertHasRow(
            missing, {
                'biobank_id': to_client_biobank_id(
                    p_two_days_missing.biobankId),
                'sent_order_id': 'OTwoDaysMissingOrder',
                'sent_test': BIOBANK_TESTS[0]
            })
        exporter.assertHasRow(
            missing, {
                'biobank_id': to_client_biobank_id(
                    p_two_days_missing.biobankId),
                'sent_order_id': 'OTwoDaysMissingOrder',
                'sent_test': BIOBANK_TESTS[1]
            })

        # 3 orders sent, only 2 received
        multi_sample_row = exporter.assertHasRow(
            missing, {
                'biobank_id': to_client_biobank_id(p_repeated.biobankId),
                'sent_count': '3',
                'received_count': '2'
            })

        # Also verify the comma-joined fields of the row with multiple orders/samples.
        self.assertItemsEqual(
            multi_sample_row['sent_order_id'].split(','),
            ['ORepeatedOrder1', 'ORepeatedOrder0', 'ORepeatedOrder2'])
        self.assertItemsEqual(
            multi_sample_row['received_sample_id'].split(','),
            ['RepeatedSample0', 'RepeatedSample1'])

        # We don't include the old withdrawal.
        exporter.assertRowCount(withdrawals, 5)
        exporter.assertHasRow(
            withdrawals, {
                'biobank_id':
                to_client_biobank_id(p_withdrawn_old_on_time.biobankId),
                'withdrawal_time':
                database_utils.format_datetime(within_24_hours),
                'is_native_american':
                'Y'
            })
        exporter.assertHasRow(
            withdrawals, {
                'biobank_id':
                to_client_biobank_id(p_withdrawn_late_and_missing.biobankId),
                'withdrawal_time':
                database_utils.format_datetime(within_24_hours),
                'is_native_american':
                'N'
            })
        exporter.assertHasRow(
            withdrawals, {
                'biobank_id': to_client_biobank_id(
                    p_withdrawn_extra.biobankId),
                'withdrawal_time':
                database_utils.format_datetime(within_24_hours),
                'is_native_american': 'N'
            })
        exporter.assertHasRow(
            withdrawals, {
                'biobank_id': to_client_biobank_id(
                    p_withdrawn_old_extra.biobankId),
                'withdrawal_time':
                database_utils.format_datetime(within_24_hours),
                'is_native_american': 'Y'
            })
        exporter.assertHasRow(
            withdrawals, {
                'biobank_id':
                to_client_biobank_id(p_withdrawn_race_change.biobankId),
                'withdrawal_time':
                database_utils.format_datetime(within_24_hours),
                'is_native_american':
                'N'
            })
Exemplo n.º 16
0
    def to_client_json(self, model):
        result = model.asdict()
        # Participants that withdrew more than 48 hours ago should have fields other than
        # WITHDRAWN_PARTICIPANT_FIELDS cleared.
        if (model.withdrawalStatus == WithdrawalStatus.NO_USE and
            (model.withdrawalTime is None or model.withdrawalTime <
             clock.CLOCK.now() - WITHDRAWN_PARTICIPANT_VISIBILITY_TIME)):
            result = {k: result.get(k) for k in WITHDRAWN_PARTICIPANT_FIELDS}

        elif model.withdrawalStatus != WithdrawalStatus.NO_USE and \
          model.suspensionStatus == SuspensionStatus.NO_CONTACT:
            for i in SUSPENDED_PARTICIPANT_FIELDS:
                result[i] = UNSET

        result['participantId'] = to_client_participant_id(model.participantId)
        biobank_id = result.get('biobankId')
        if biobank_id:
            result['biobankId'] = to_client_biobank_id(biobank_id)
        date_of_birth = result.get('dateOfBirth')
        if date_of_birth:
            result['ageRange'] = get_bucketed_age(date_of_birth,
                                                  clock.CLOCK.now())
        else:
            result['ageRange'] = UNSET

        if result.get('primaryLanguage') is None:
            result['primaryLanguage'] = UNSET

        if 'organizationId' in result:
            result['organization'] = result['organizationId']
            del result['organizationId']
            format_json_org(result, self.organization_dao, 'organization')

        if result.get('genderIdentityId'):
            del result[
                'genderIdentityId']  # deprecated in favor of genderIdentity

        # Note: leaving for future use if we go back to using a relationship to PatientStatus table.
        # def format_patient_status_record(status_obj):
        #   status_dict = self.patient_status_dao.to_client_json(status_obj)
        #   return {
        #     'organization': status_dict['organization'],
        #     'status': status_dict['patient_status'],
        #   }
        # result['patientStatus'] = map(format_patient_status_record, model.patientStatus)
        result['patientStatus'] = model.patientStatus

        format_json_hpo(result, self.hpo_dao, 'hpoId')
        result['awardee'] = result['hpoId']
        _initialize_field_type_sets()
        for fieldname in _DATE_FIELDS:
            format_json_date(result, fieldname)
        for fieldname in _CODE_FIELDS:
            format_json_code(result, self.code_dao, fieldname)
        for fieldname in _ENUM_FIELDS:
            format_json_enum(result, fieldname)
        for fieldname in _SITE_FIELDS:
            format_json_site(result, self.site_dao, fieldname)
        if (model.withdrawalStatus == WithdrawalStatus.NO_USE
                or model.suspensionStatus == SuspensionStatus.NO_CONTACT):
            result['recontactMethod'] = 'NO_CONTACT'
        # Strip None values.
        result = {k: v for k, v in result.iteritems() if v is not None}

        return result