def _create_daklapack_order(order_dict):
    order_dict[ORDER_ID_KEY] = str(uuid.uuid4())

    with Transaction() as t:
        try:
            daklapack_order = DaklapackOrder.from_api(**order_dict)
        except ValueError as e:
            raise RepoException(e)

        # The Daklapack API wants a *list* of orders, and we are submitting one
        # at a time, so we have a list of one item :)
        post_response = post_daklapack_orders(
            [daklapack_order.order_structure])
        if post_response.status_code >= 400:
            # for now, very basic error handling--just pass on dak api error
            response_msg = {"order_address":
                            daklapack_order.order_structure[ADDR_DICT_KEY],
                            "order_success": False,
                            "daklapack_api_error_msg":
                                post_response.get_data(as_text=True),
                            "daklapack_api_error_code":
                            post_response.status_code}
            return response_msg

        # write order to db
        admin_repo = AdminRepo(t)
        order_id = admin_repo.create_daklapack_order(daklapack_order)
        t.commit()

    status_msg = {"order_address":
                  daklapack_order.order_structure[ADDR_DICT_KEY],
                  "order_success": True,
                  "order_id": order_id}
    return status_msg
def get_daklapack_articles(token_info):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        dak_article_dicts = admin_repo.get_daklapack_articles()
        return jsonify(dak_article_dicts), 200
 def test_retrieve_diagnostics_by_barcode_nonexistent(self):
     with Transaction() as t:
         admin_repo = AdminRepo(t)
         # Uhh, should this return a 404 not found or just an empty
         # diagnostic object...?
         diag = admin_repo.retrieve_diagnostics_by_barcode('NotABarcode :D')
         self.assertIsNone(diag)
def project_statistics_detailed(token_info, project_id):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        summary = admin_repo.get_project_detailed_statistics(project_id)
        return jsonify(summary), 200
def teardown_test_data():
    with Transaction() as t:
        acct_repo = AccountRepo(t)
        admin_repo = AdminRepo(t)
        acct_repo.delete_account(ACCT_ID_1)
        admin_repo.delete_project_by_name(DUMMY_PROJ_NAME)
        t.commit()
Example #6
0
    def test_create_project_success_full(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            # Note: using dict_cursor here so results are DictRow
            # objects that can easily be converted to a dictionary
            with t.dict_cursor() as cur:
                cur.execute("SELECT project "
                            "FROM barcodes.project "
                            "WHERE project = 'full_test_proj'")
                self.assertEqual(len(cur.fetchall()), 0)

                full_project_dict = self._FULL_PROJECT_DICT.copy()
                full_project_dict[p.PROJ_NAME_KEY] = 'full_test_proj'
                input = p.Project.from_dict(full_project_dict)

                output_id = admin_repo.create_project(input)

                cur.execute("SELECT * "
                            "FROM barcodes.project "
                            "WHERE project = 'full_test_proj'")
                row = cur.fetchone()
                obs_dict = dict(row)
                full_project_dict["project_id"] = output_id
                full_project_dict[p.DB_PROJ_NAME_KEY] = \
                    full_project_dict.pop(p.PROJ_NAME_KEY)
                self.assertEqual(obs_dict, full_project_dict)
    def test_update_project(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            proj_id = admin_repo.create_project(
                Project(project_name=DUMMY_PROJ_NAME,
                        is_microsetta=False,
                        bank_samples=False))
            t.commit()

        # create post input json
        input_json = json.dumps(self.FULL_PROJ_INFO)

        # execute project put (update)
        response = self.client.put(f"/api/admin/projects/{proj_id}",
                                   content_type='application/json',
                                   data=input_json,
                                   headers=MOCK_HEADERS)

        # check response code
        self.assertEqual(204, response.status_code)

        with Transaction() as t:
            with t.dict_cursor() as cur:
                cur.execute(
                    "select * FROM project "
                    "WHERE "
                    "project_id = %s", (proj_id, ))
                row = cur.fetchone()
                stored_result = dict(row)

        expected_result = self.FULL_PROJ_INFO.copy()
        expected_result["project"] = expected_result.pop("project_name")
        expected_result["project_id"] = proj_id
        self.assertEqual(expected_result, stored_result)
def create_project(body, token_info):
    validate_admin_access(token_info)

    project_name = body['project_name']
    is_microsetta = body['is_microsetta']
    bank_samples = body['bank_samples']
    plating_start_date = body.get('plating_start_date')

    if plating_start_date is not None:
        try:
            plating_start_date = datetime.datetime.strptime(
                plating_start_date, "%Y-%m-%d")
        except ValueError:
            raise BadRequest(
                "plating start date '{0}' is not a valid date in YYYY-MM-DD "
                "format".format(plating_start_date))

    if len(project_name) == 0:
        return jsonify(code=400, message="No project name provided"), 400

    if not bank_samples and plating_start_date is not None:
        raise RepoException("Plating start date cannot be set for"
                            " unbanked projects")

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        admin_repo.create_project(project_name, is_microsetta, bank_samples,
                                  plating_start_date)
        t.commit()

    return {}, 201
Example #9
0
def per_sample_summary(email, project, strip_sampleid):
    with Transaction() as t:
        admin = AdminRepo(t)
        project_name = admin.get_project_name(project)

    summaries = per_sample(project,
                           barcodes=None,
                           strip_sampleid=strip_sampleid)
    df = pd.DataFrame(summaries)
    _, path = tempfile.mkstemp()
    df.to_csv(path)
    date = datetime.datetime.now().strftime("%d%b%Y")
    filename = f'project-{project_name}-summary-{date}.csv'

    # NOTE: we are not using .delay so this action remains
    # within the current celery task
    template_args = {'date': date, 'project': project_name}
    send_basic_email(email,
                     f"[TMI-summary] Project {project}",
                     'email/sample_summary',
                     list(template_args),
                     template_args,
                     "EMAIL",
                     "EMAIL_PER_PROJECT_SUMMARY",
                     attachment_filepath=path,
                     attachment_filename=filename)
    os.remove(path)
def sample_pulldown_multiple_survey(token_info, sample_barcode):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        sample_pulldown = admin_repo.get_survey_metadata(sample_barcode)
    return jsonify(sample_pulldown), 200
Example #11
0
 def test_get_daklapack_articles(self):
     with Transaction() as t:
         admin_repo = AdminRepo(t)
         articles = admin_repo.get_daklapack_articles()
         self.assertEqual(24, len(articles))
         first_article = articles[0]
         first_article.pop("dak_article_id")
         self.assertEqual(FIRST_DAKLAPACK_ARTICLE, first_article)
def get_projects(token_info, include_stats, is_active=None):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        projects_list = admin_repo.get_projects(include_stats, is_active)
        result = [x.to_api() for x in projects_list]
        return jsonify(result), 200
def update_project(project_id, body):
    project = Project.from_dict(body)
    with Transaction() as t:
        admin_repo = AdminRepo(t)
        admin_repo.update_project(project_id, project)
        t.commit()

        return '', 204
Example #14
0
    def test_search_kit_id(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            diag = admin_repo.retrieve_diagnostics_by_kit_id('test')
            self.assertIsNotNone(diag)
            self.assertIsNotNone(diag['kit'])

            diag = admin_repo.retrieve_diagnostics_by_kit_id('NotAKitId!!!!')
            self.assertIsNone(diag)
def search_email(token_info, email):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        diag = admin_repo.retrieve_diagnostics_by_email(email)
        if diag is None:
            return jsonify(code=404, message="Email not found"), 404
        return jsonify(diag), 200
 def test_scan_barcode_error_nonexistent(self):
     with Transaction() as t:
         admin_repo = AdminRepo(t)
         with self.assertRaises(NotFound):
             admin_repo.scan_barcode("THIZIZNOTAREALBARCODEISWARE", {
                 "sample_status": "Abc",
                 "technician_notes": "123"
             })
             self.fail("Shouldn't get here")
def search_kit_id(token_info, kit_id):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        diag = admin_repo.retrieve_diagnostics_by_kit_id(kit_id)
        if diag is None:
            return jsonify(code=404, message="Kit ID not found"), 404
        return jsonify(diag), 200
 def test_retrieve_diagnostics_by_barcode_nonexistent(self):
     with Transaction() as t:
         # TODO FIXME HACK:  Need to build mock barcodes rather than using
         #  these fixed ones
         admin_repo = AdminRepo(t)
         # Uhh, should this return a 404 not found or just an empty
         # diagnostic object...?
         diag = admin_repo.retrieve_diagnostics_by_barcode('NotABarcode :D')
         self.assertIsNone(diag)
def search_barcode(token_info, sample_barcode):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        diag = admin_repo.retrieve_diagnostics_by_barcode(sample_barcode)
        if diag is None:
            return jsonify(code=404, message="Barcode not found"), 404
        return jsonify(diag), 200
Example #20
0
    def test_detailed_project_statistics(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)

            agp_summary = admin_repo.get_project_detailed_statistics(1)
            self.assertIn('project_id', agp_summary)
            self.assertIn('project_name', agp_summary)
            self.assertIn('number_of_samples', agp_summary)
            self.assertIn('number_of_samples_scanned_in', agp_summary)
            self.assertIn('sample_status_counts', agp_summary)
 def test_retrieve_diagnostics_by_barcode_not_agp(self):
     with Transaction() as t:
         admin_repo = AdminRepo(t)
         diag = admin_repo.retrieve_diagnostics_by_barcode('000044481')
         self.assertIsNotNone(diag['barcode_info'])
         self.assertIsNone(diag['account'])
         self.assertIsNone(diag['source'])
         self.assertIsNone(diag['sample'])
         self.assertGreater(len(diag['scans_info']), 0)
         self.assertGreater(len(diag['projects_info']), 0)
Example #22
0
    def test_summary_statistics(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)

            summary = admin_repo.get_project_summary_statistics()
            self.assertGreater(len(summary), 1)
            for stats in summary:
                self.assertIn('project_id', stats)
                self.assertIn('project_name', stats)
                self.assertIn('number_of_samples', stats)
    def test_search_email(self):
        with Transaction() as t:
            admin_repo = AdminRepo(t)
            diag = admin_repo.retrieve_diagnostics_by_email(
                'yqrc&[email protected]')
            self.assertIsNotNone(diag)
            self.assertEqual(len(diag['accounts']), 1)

            diag = admin_repo.retrieve_diagnostics_by_email('.com')
            self.assertIsNotNone(diag)
            self.assertGreater(len(diag['accounts']), 1)
 def test_retrieve_diagnostics_by_barcode_wo_extra_info(self):
     with Transaction() as t:
         # TODO FIXME HACK:  Need to build mock barcodes rather than using
         #  these fixed ones
         admin_repo = AdminRepo(t)
         diag = admin_repo.retrieve_diagnostics_by_barcode('000033903')
         self.assertIsNotNone(diag['barcode_info'])
         self.assertIsNone(diag['account'])
         self.assertIsNone(diag['source'])
         self.assertIsNone(diag['sample'])
         self.assertGreater(len(diag['projects_info']), 0)
         self.assertEqual(len(diag['scans_info']), 0)
def teardown_test_data():
    with Transaction() as t:
        acct_repo = AccountRepo(t)
        admin_repo = AdminRepo(t)
        acct_repo.delete_account(ACCT_ID_1)
        admin_repo.delete_project_by_name(DUMMY_PROJ_NAME)
        with t.cursor() as cur:
            cur.execute("UPDATE barcodes.project"
                        " SET is_active = TRUE"
                        " WHERE project_id = 2")

        t.commit()
def barcode_query(body, token_info):
    # Validating admin access is absolutely critical here
    # Failing to do so enables sql query access
    # to non admin users
    validate_admin_access(token_info)

    with Transaction() as t:
        repo = AdminRepo(t)
        cond, cond_params = build_condition(body)
        barcodes = repo.search_barcode(cond, cond_params)
        t.rollback()  # Queries don't need to commit changes.

    return jsonify(barcodes), 200
def scan_barcode(token_info, sample_barcode, body):
    validate_admin_access(token_info)

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        scan_id = admin_repo.scan_barcode(sample_barcode, body)
        t.commit()

    response = jsonify({"scan_id": scan_id})
    response.status_code = 201
    response.headers['Location'] = '/api/admin/search/samples/%s' % \
                                   sample_barcode
    return response
    def test_retrieve_diagnostics_by_barcode_w_scans(self):
        def make_tz_datetime(y, m, d):
            return datetime.datetime(y,
                                     m,
                                     d,
                                     0,
                                     0,
                                     tzinfo=psycopg2.tz.FixedOffsetTimezone(
                                         offset=-420, name=None))

        # Non-AGP barcode so no acct, source, or sample;
        # also no preexisting scans in test db
        test_barcode = '000004531'
        first_scan_id = 'f7fd3022-3a9c-4f79-b92c-5cebd83cba38'
        second_scan_id = '76aec821-aa28-4dea-a796-2cfd1276f78c'

        first_scan = {
            "barcode_scan_id": first_scan_id,
            "barcode": test_barcode,
            "scan_timestamp": make_tz_datetime(2017, 7, 16),
            "sample_status": 'no-registered-account',
            "technician_notes": "huh?"
        }

        second_scan = {
            "barcode_scan_id": second_scan_id,
            "barcode": test_barcode,
            "scan_timestamp": make_tz_datetime(2020, 12, 4),
            "sample_status": 'sample-is-valid',
            "technician_notes": None
        }
        try:
            add_dummy_scan(first_scan)
            add_dummy_scan(second_scan)

            with Transaction() as t:
                admin_repo = AdminRepo(t)
                diag = admin_repo.retrieve_diagnostics_by_barcode(test_barcode)
                self.assertIsNotNone(diag['barcode_info'])
                self.assertIsNone(diag['account'])
                self.assertIsNone(diag['source'])
                self.assertIsNone(diag['sample'])
                self.assertGreater(len(diag['projects_info']), 0)
                self.assertEqual(len(diag['scans_info']), 2)
                # order matters in the returned vals, so test that
                self.assertEqual(diag['scans_info'][0], first_scan)
                self.assertEqual(diag['scans_info'][1], second_scan)
                self.assertEqual(diag['latest_scan'], second_scan)
        finally:
            delete_test_scan(first_scan_id)
            delete_test_scan(second_scan_id)
def create_project(body, token_info):
    validate_admin_access(token_info)

    project_name = body['project_name']
    is_microsetta = body['is_microsetta']

    if len(project_name) == 0:
        return jsonify(code=400, message="No project name provided"), 400

    with Transaction() as t:
        admin_repo = AdminRepo(t)
        admin_repo.create_project(project_name, is_microsetta)
        t.commit()

    return {}, 201
Example #30
0
    def test_process_order_articles_unknown_status(self):
        with Transaction() as t:
            dummy_orders = self.make_dummy_dak_orders(t)
            an_order_id = dummy_orders[0][0]
            admin_repo = AdminRepo(t)

            # NB: these have to be patched *where they will be looked up*, not
            # where they are originally defined; see
            # https://docs.python.org/3/library/unittest.mock.html#where-to-patch
            with patch("microsetta_private_api.admin.daklapack_communication."
                       "get_daklapack_order_details") as mock_dak_order_info:
                # NB: this is returning the same json as for the "sent"
                # case; this json says each article was sent (which would
                # not be the case in the "unknown" case) but that field isn't
                # used for the "unknown" case so I am not bothering to make a
                # whole new input to change that field for verisimilitude
                mock_dak_order_info.side_effect = [
                    make_test_response(200, self.ARTICLES_INFO)
                ]

                with self.assertRaisesRegex(
                        ValueError,
                        "Order 7ed917ef-0c4d-431a-9aa0-0a1f4f41f44b "
                        "has an unexpected status: InProduction"):
                    process_order_articles(admin_repo, an_order_id,
                                           "InProduction",
                                           "2021-02-26T08:30:18.805519Z")