def retrieve_diagnostics_by_kit_id(self, supplied_kit_id):
        kit_repo = KitRepo(self._transaction)
        kit = kit_repo.get_kit_all_samples(supplied_kit_id)

        if kit is None:
            return None

        sample_assoc = []
        for sample in kit.samples:
            sample_assoc.append(
                self.retrieve_diagnostics_by_barcode(sample.barcode,
                                                     grab_kit=False))

        with self._transaction.dict_cursor() as cur:
            cur.execute(
                "SELECT "
                "ag_login_id as account_id "
                "FROM "
                "ag_kit "
                "WHERE "
                "supplied_kit_id = %s",
                (supplied_kit_id,))
            row = cur.fetchone()

        pre_microsetta_acct = None
        if row['account_id'] is not None:
            acct_repo = AccountRepo(self._transaction)
            # This kit predated the microsetta migration, let's pull in the
            # account info associated with it
            pre_microsetta_acct = acct_repo.get_account(row['account_id'])

        # obtain information on any accounts created using the kit ID
        with self._transaction.dict_cursor() as cur:
            cur.execute(
                "SELECT id as account_id "
                "FROM "
                "account "
                "WHERE "
                "created_with_kit_id = %s",
                (supplied_kit_id, ))
            rows = cur.fetchall()

        accounts_created = None
        if len(rows) > 0:
            acct_repo = AccountRepo(self._transaction)
            accounts_created = [acct_repo.get_account(row['account_id'])
                                for row in rows]

        diagnostic = {
            'accounts_created': accounts_created,
            'kit_id': kit.id,
            'supplied_kit_id': supplied_kit_id,
            'kit': kit,
            'pre_microsetta_acct': pre_microsetta_acct,
            'sample_diagnostic_info': sample_assoc
        }

        return diagnostic
Esempio n. 2
0
def read_kit(kit_name):
    # NOTE:  Nothing in this route requires a particular user to be logged in,
    # so long as the user has -an- account.

    with Transaction() as t:
        kit_repo = KitRepo(t)
        kit = kit_repo.get_kit_unused_samples(kit_name)
        if kit is None:
            return jsonify(code=404, message="No such kit"), 404
        return jsonify(kit.to_api()), 200
Esempio n. 3
0
def register_account(body, token_info):
    # First register with AuthRocket, then come here to make the account
    new_acct_id = str(uuid.uuid4())
    body["id"] = new_acct_id
    # Account.from_dict requires a kit_name, even if blank
    kit_name = body.get("kit_name", "")
    body["kit_name"] = kit_name
    code = body.get("code", "")
    body["code"] = code

    account_obj = Account.from_dict(body, token_info[JWT_ISS_CLAIM_KEY],
                                    token_info[JWT_SUB_CLAIM_KEY])

    if kit_name == "" and code == "":
        return jsonify(code=400,
                       message="Account registration requires "
                       "valid kit ID or activation code"), 400

    with Transaction() as t:
        activation_repo = ActivationRepo(t)
        if code != "":
            can_activate, cause = activation_repo.can_activate_with_cause(
                body["email"], code)
            if not can_activate:
                return jsonify(code=404, message=cause), 404
            else:
                activation_repo.use_activation_code(body["email"], code)

        if kit_name != "":
            kit_repo = KitRepo(t)
            kit = kit_repo.get_kit_all_samples(kit_name)
            if kit is None:
                return jsonify(code=404, message="Kit name not found"), 404

        acct_repo = AccountRepo(t)
        acct_repo.create_account(account_obj)
        new_acct = acct_repo.get_account(new_acct_id)
        t.commit()

    response = jsonify(new_acct.to_api())
    response.status_code = 201
    response.headers['Location'] = '/api/accounts/%s' % new_acct_id
    return response
Esempio n. 4
0
def register_account(body, token_info):
    # First register with AuthRocket, then come here to make the account
    new_acct_id = str(uuid.uuid4())
    body["id"] = new_acct_id
    account_obj = Account.from_dict(body, token_info[JWT_ISS_CLAIM_KEY],
                                    token_info[JWT_SUB_CLAIM_KEY])

    with Transaction() as t:
        kit_repo = KitRepo(t)
        kit = kit_repo.get_kit_all_samples(body['kit_name'])
        if kit is None:
            return jsonify(code=404, message="Kit name not found"), 404

        acct_repo = AccountRepo(t)
        acct_repo.create_account(account_obj)
        new_acct = acct_repo.get_account(new_acct_id)
        t.commit()

    response = jsonify(new_acct.to_api())
    response.status_code = 201
    response.headers['Location'] = '/api/accounts/%s' % new_acct_id
    return response
Esempio n. 5
0
    def retrieve_diagnostics_by_barcode(self, sample_barcode, grab_kit=True):
        def _rows_to_dicts_list(rows):
            return [dict(x) for x in rows]

        with self._transaction.dict_cursor() as cur:
            ids = self._get_ids_relevant_to_barcode(sample_barcode)

            if ids is None:
                ids = {}

            # default for not found is None
            sample_id = ids.get("sample_id")
            source_id = ids.get("source_id")
            account_id = ids.get("account_id")
            # NB: this is the true UUID kit id (the primary key of
            # ag.ag_kit), NOT the kit's participant-facing string "id"
            kit_id = ids.get("kit_id")

            account = None
            source = None
            sample = None
            kit = None

            # get sample object for this barcode, if any
            if sample_id is not None:
                sample_repo = SampleRepo(self._transaction)
                sample = sample_repo._get_sample_by_id(sample_id)

            # get account object for this barcode, if any
            if account_id is not None:
                account_repo = AccountRepo(self._transaction)
                account = account_repo.get_account(account_id)

            # and source object for this barcode, if any
            if source_id is not None:
                source_repo = SourceRepo(self._transaction)
                source = source_repo.get_source(account_id, source_id)

            # get (partial) projects_info list for this barcode
            query = f"""
                    SELECT {p.DB_PROJ_NAME_KEY}, {p.IS_MICROSETTA_KEY},
                    {p.BANK_SAMPLES_KEY}, {p.PLATING_START_DATE_KEY}
                    FROM barcodes.project
                    INNER JOIN barcodes.project_barcode
                    USING (project_id)
                    WHERE barcode=%s;"""

            cur.execute(query, (sample_barcode, ))
            # this can't be None; worst-case is an empty list
            projects_info = _rows_to_dicts_list(cur.fetchall())

            # get scans_info list for this barcode
            # NB: ORDER MATTERS here. Do not change the order unless you
            # are positive you know what already depends on it.
            cur.execute(
                "SELECT barcode_scan_id, barcode, "
                "scan_timestamp, sample_status, "
                "technician_notes "
                "FROM barcodes.barcode_scans "
                "WHERE barcode=%s "
                "ORDER BY scan_timestamp asc", (sample_barcode, ))
            # this can't be None; worst-case is an empty list
            scans_info = _rows_to_dicts_list(cur.fetchall())

            latest_scan = None
            if len(scans_info) > 0:
                # NB: the correctness of this depends on the scans (queried
                # right above) being in ascending order by timestamp
                latest_scan = scans_info[len(scans_info) - 1]

            # get details about this barcode itself; CAN be None if the
            # barcode doesn't exist in db
            barcode_info = None
            cur.execute(
                "SELECT barcode, assigned_on, status, "
                "sample_postmark_date, biomass_remaining, "
                "sequencing_status, obsolete, "
                "create_date_time, kit_id "
                "FROM barcodes.barcode "
                "WHERE barcode = %s", (sample_barcode, ))
            barcode_row = cur.fetchone()
            if barcode_row is not None:
                barcode_info = dict(barcode_row)

            if account is None and source is None and sample is None and \
                    len(projects_info) == 0 and len(scans_info) == 0 \
                    and barcode_info is None:
                return None

            diagnostic = {
                "account": account,
                "source": source,
                "sample": sample,
                "latest_scan": latest_scan,
                "scans_info": scans_info,
                "barcode_info": barcode_info,
                "projects_info": projects_info
            }

            if grab_kit:
                # get kit object
                if kit_id is not None:
                    kit_repo = KitRepo(self._transaction)
                    kit = kit_repo.get_kit_all_samples_by_kit_id(kit_id)
                diagnostic["kit"] = kit

            return diagnostic
    def retrieve_diagnostics_by_barcode(self, sample_barcode, grab_kit=True):
        def _rows_to_dicts_list(rows):
            return [dict(x) for x in rows]

        with self._transaction.dict_cursor() as cur:
            ids = self._get_ids_relevant_to_barcode(sample_barcode)

            if ids is None:
                sample_id = None
                source_id = None
                account_id = None
                kit_id = None
            else:
                sample_id = ids["sample_id"]
                source_id = ids["source_id"]
                account_id = ids["account_id"]
                kit_id = ids["kit_id"]

            account = None
            source = None
            sample = None
            kit = None

            # get sample object for this barcode
            if sample_id is not None:
                sample_repo = SampleRepo(self._transaction)
                sample = sample_repo._get_sample_by_id(sample_id)

            # get account and source objects for this barcode
            if source_id is not None and account_id is not None:
                account_repo = AccountRepo(self._transaction)
                source_repo = SourceRepo(self._transaction)
                account = account_repo.get_account(account_id)
                source = source_repo.get_source(account_id, source_id)

            # get projects_info list for this barcode
            cur.execute("SELECT project, is_microsetta, "
                        "bank_samples, plating_start_date "
                        "FROM barcodes.project "
                        "INNER JOIN barcodes.project_barcode "
                        "USING (project_id) "
                        "WHERE barcode=%s",
                        (sample_barcode,))
            # this can't be None; worst-case is an empty list
            projects_info = _rows_to_dicts_list(cur.fetchall())

            # get scans_info list for this barcode
            # NB: ORDER MATTERS here. Do not change the order unless you
            # are positive you know what already depends on it.
            cur.execute("SELECT barcode_scan_id, barcode, "
                        "scan_timestamp, sample_status, "
                        "technician_notes "
                        "FROM barcodes.barcode_scans "
                        "WHERE barcode=%s "
                        "ORDER BY scan_timestamp asc",
                        (sample_barcode,))
            # this can't be None; worst-case is an empty list
            scans_info = _rows_to_dicts_list(cur.fetchall())

            latest_scan = None
            if len(scans_info) > 0:
                # NB: the correctness of this depends on the scans (queried
                # right above) being in ascending order by timestamp
                latest_scan = scans_info[len(scans_info)-1]

            # get details about this barcode itself; CAN be None if the
            # barcode doesn't exist in db
            barcode_info = None
            cur.execute("SELECT barcode, assigned_on, status, "
                        "sample_postmark_date, biomass_remaining, "
                        "sequencing_status, obsolete, "
                        "create_date_time, kit_id "
                        "FROM barcodes.barcode "
                        "WHERE barcode = %s",
                        (sample_barcode,))
            barcode_row = cur.fetchone()
            if barcode_row is not None:
                barcode_info = dict(barcode_row)

            if account is None and source is None and sample is None and \
                    len(projects_info) == 0 and len(scans_info) == 0 \
                    and barcode_info is None:
                return None

            diagnostic = {
                "account": account,
                "source": source,
                "sample": sample,
                "latest_scan": latest_scan,
                "scans_info": scans_info,
                "barcode_info": barcode_info,
                "projects_info": projects_info
            }

            if grab_kit:
                # get kit object
                if kit_id is not None:
                    kit_repo = KitRepo(self._transaction)
                    kit = kit_repo.get_kit_all_samples_by_kit_id(kit_id)
                diagnostic["kit"] = kit

            return diagnostic
Esempio n. 7
0
    def retrieve_diagnostics_by_barcode(self, sample_barcode, grab_kit=True):
        with self._transaction.dict_cursor() as cur:
            ids = self._get_ids_relevant_to_barcode(sample_barcode)

            if ids is None:
                sample_id = None
                source_id = None
                account_id = None
                kit_id = None
            else:
                sample_id = ids["sample_id"]
                source_id = ids["source_id"]
                account_id = ids["account_id"]
                kit_id = ids["kit_id"]

            account = None
            source = None
            sample = None
            kit = None

            if sample_id is not None:
                sample_repo = SampleRepo(self._transaction)
                sample = sample_repo._get_sample_by_id(sample_id)

            if source_id is not None and account_id is not None:
                account_repo = AccountRepo(self._transaction)
                source_repo = SourceRepo(self._transaction)
                account = account_repo.get_account(account_id)
                source = source_repo.get_source(account_id, source_id)

            if kit_id is not None and grab_kit:
                kit_repo = KitRepo(self._transaction)
                kit = kit_repo.get_kit_all_samples_by_kit_id(kit_id)

            cur.execute("SELECT * from barcodes.barcode "
                        "LEFT OUTER JOIN barcodes.project_barcode "
                        "USING (barcode) "
                        "LEFT OUTER JOIN barcodes.project "
                        "USING (project_id) "
                        "where barcode=%s",
                        (sample_barcode,))
            barcode_info = cur.fetchall()

            # How to unwrap a psycopg2 DictRow.  I feel dirty.
            barcode_info = [{k: v for k, v in x.items()}
                            for x in barcode_info]  # Get Inceptioned!!

            # Collapse info from joined project_barcode and project tables
            # into array within barcode_info
            if barcode_info:
                first = barcode_info[0]
                first['projects'] = [
                    {
                        'project_id': r['project_id'],
                        'project': r['project']
                    }
                    for r in barcode_info]
                del first['project_id']
                del first['project']
                barcode_info = first
            else:
                barcode_info = None

            if account is None and \
                    source is None and \
                    sample is None and \
                    barcode_info is None:
                return None

            diagnostic = {
                "barcode": sample_barcode,
                "account": account,
                "source": source,
                "sample": sample,
                "barcode_info": barcode_info
            }

            if grab_kit:
                diagnostic["kit"] = kit

            return diagnostic
def query_email_stats(body, token_info):
    validate_admin_access(token_info)

    email_list = body.get("emails", [])
    project = body.get("project")

    results = []
    with Transaction() as t:
        account_repo = AccountRepo(t)
        kit_repo = KitRepo(t)
        source_repo = SourceRepo(t)
        sample_repo = SampleRepo(t)

        for email in email_list:
            result = {'email': email, 'project': project}
            results.append(result)
            # can use internal lookup by email, because we have admin access
            account = account_repo._find_account_by_email(email)  # noqa
            if account is None:
                result['summary'] = "No Account"
                continue
            else:
                result['account_id'] = account.id
                result['creation_time'] = account.creation_time
                result['kit_name'] = account.created_with_kit_id

            if account.created_with_kit_id is not None:
                unused = kit_repo.get_kit_unused_samples(
                             account.created_with_kit_id
                         )
                if unused is None:
                    result['unclaimed-samples-in-kit'] = 0
                else:
                    result['unclaimed-samples-in-kit'] = len(unused.samples)

            sample_statuses = defaultdict(int)
            sources = source_repo.get_sources_in_account(account.id)

            samples_in_project = 0
            for source in sources:
                samples = sample_repo.get_samples_by_source(account.id,
                                                            source.id)
                for sample in samples:
                    if project is not None and \
                       project != "" and \
                       project not in sample.sample_projects:
                        continue
                    samples_in_project += 1
                    sample_status = sample_repo.get_sample_status(
                        sample.barcode,
                        sample._latest_scan_timestamp  # noqa
                    )
                    if sample_status is None:
                        sample_status = "never-scanned"
                    sample_statuses[sample_status] += 1
            result.update(sample_statuses)

            if result.get('unclaimed-samples-in-kit', 0) > 0:
                result['summary'] = 'Possible Unreturned Samples'
            elif samples_in_project == 0:
                result['summary'] = "No Samples In Specified Project"
            elif result.get('sample-is-valid') == samples_in_project:
                result['summary'] = 'All Samples Valid'
            else:
                result['summary'] = 'May Require User Interaction'

    return jsonify(results), 200