2019-12-18 19:02:17 +00:00
|
|
|
# Set environment variable to testing before loading.
|
|
|
|
# IMPORTANT - Environment must be loaded before app, models, etc....
|
|
|
|
import os
|
2020-05-25 16:29:05 +00:00
|
|
|
|
2020-06-11 15:49:07 +00:00
|
|
|
from flask import g
|
2020-05-25 16:29:05 +00:00
|
|
|
from sqlalchemy import Sequence
|
|
|
|
|
2020-05-22 18:37:49 +00:00
|
|
|
os.environ["TESTING"] = "true"
|
|
|
|
|
|
|
|
import json
|
2020-01-24 14:35:14 +00:00
|
|
|
import unittest
|
2020-02-27 15:30:16 +00:00
|
|
|
import urllib.parse
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
import datetime
|
2020-02-27 15:30:16 +00:00
|
|
|
|
2020-06-11 20:39:00 +00:00
|
|
|
from crc.models.approval import ApprovalModel, ApprovalStatus
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
from crc.models.protocol_builder import ProtocolBuilderStatus
|
2020-03-19 21:13:30 +00:00
|
|
|
from crc.models.study import StudyModel
|
2020-03-05 18:25:28 +00:00
|
|
|
from crc.services.file_service import FileService
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
from crc.services.study_service import StudyService
|
2020-03-05 18:25:28 +00:00
|
|
|
from crc.models.file import FileModel, FileDataModel, CONTENT_TYPES
|
2020-03-19 21:13:30 +00:00
|
|
|
from crc.models.workflow import WorkflowSpecModel, WorkflowSpecModelSchema, WorkflowModel
|
2020-02-27 15:30:16 +00:00
|
|
|
from crc.models.user import UserModel
|
2019-12-18 19:02:17 +00:00
|
|
|
|
2020-01-14 16:45:12 +00:00
|
|
|
from crc import app, db, session
|
2019-12-30 18:03:57 +00:00
|
|
|
from example_data import ExampleDataLoader
|
2019-12-18 19:02:17 +00:00
|
|
|
|
2020-05-27 18:36:10 +00:00
|
|
|
#UNCOMMENT THIS FOR DEBUGGING SQL ALCHEMY QUERIES
|
|
|
|
import logging
|
|
|
|
logging.basicConfig()
|
2019-12-27 18:50:03 +00:00
|
|
|
|
|
|
|
|
2020-01-24 14:35:14 +00:00
|
|
|
class BaseTest(unittest.TestCase):
|
2020-02-27 15:30:16 +00:00
|
|
|
""" Great class to inherit from, as it sets up and tears down classes
|
|
|
|
efficiently when we have a database in place.
|
|
|
|
"""
|
2019-11-21 14:22:42 +00:00
|
|
|
|
2020-05-22 18:37:49 +00:00
|
|
|
if not app.config['TESTING']:
|
2020-05-22 22:25:00 +00:00
|
|
|
raise (Exception("INVALID TEST CONFIGURATION. This is almost always in import order issue."
|
|
|
|
"The first class to import in each test should be the base_test.py file."))
|
2020-05-22 18:37:49 +00:00
|
|
|
|
2019-11-21 14:22:42 +00:00
|
|
|
auths = {}
|
2020-02-27 15:30:16 +00:00
|
|
|
test_uid = "dhf8r"
|
2019-11-21 14:22:42 +00:00
|
|
|
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
users = [
|
|
|
|
{
|
|
|
|
'uid':'dhf8r',
|
|
|
|
'email_address':'dhf8r@virginia.EDU',
|
|
|
|
'display_name':'Daniel Harold Funk',
|
|
|
|
'affiliation':'staff@virginia.edu;member@virginia.edu',
|
|
|
|
'eppn':'dhf8r@virginia.edu',
|
|
|
|
'first_name':'Daniel',
|
|
|
|
'last_name':'Funk',
|
|
|
|
'title':'SOFTWARE ENGINEER V'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
studies = [
|
|
|
|
{
|
|
|
|
'id':0,
|
|
|
|
'title':'The impact of fried pickles on beer consumption in bipedal software developers.',
|
|
|
|
'last_updated':datetime.datetime.now(),
|
2020-04-21 21:13:30 +00:00
|
|
|
'protocol_builder_status':ProtocolBuilderStatus.ACTIVE,
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
'primary_investigator_id':'dhf8r',
|
|
|
|
'sponsor':'Sartography Pharmaceuticals',
|
|
|
|
'ind_number':'1234',
|
|
|
|
'user_uid':'dhf8r'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
'id':1,
|
|
|
|
'title':'Requirement of hippocampal neurogenesis for the behavioral effects of soft pretzels',
|
|
|
|
'last_updated':datetime.datetime.now(),
|
2020-04-21 21:13:30 +00:00
|
|
|
'protocol_builder_status':ProtocolBuilderStatus.ACTIVE,
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
'primary_investigator_id':'dhf8r',
|
|
|
|
'sponsor':'Makerspace & Co.',
|
|
|
|
'ind_number':'5678',
|
|
|
|
'user_uid':'dhf8r'
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2019-11-21 14:22:42 +00:00
|
|
|
@classmethod
|
|
|
|
def setUpClass(cls):
|
|
|
|
app.config.from_object('config.testing')
|
|
|
|
cls.ctx = app.test_request_context()
|
|
|
|
cls.app = app.test_client()
|
2020-05-19 20:11:43 +00:00
|
|
|
cls.ctx.push()
|
2019-12-18 19:02:17 +00:00
|
|
|
db.create_all()
|
2019-11-21 14:22:42 +00:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def tearDownClass(cls):
|
2020-05-19 20:11:43 +00:00
|
|
|
cls.ctx.pop()
|
2020-05-23 19:08:17 +00:00
|
|
|
db.drop_all()
|
2019-11-21 14:22:42 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
def setUp(self):
|
2020-05-19 20:11:43 +00:00
|
|
|
pass
|
2019-11-21 14:22:42 +00:00
|
|
|
|
|
|
|
def tearDown(self):
|
2020-05-19 20:11:43 +00:00
|
|
|
ExampleDataLoader.clean_db()
|
2020-06-11 15:49:07 +00:00
|
|
|
g.user = None
|
2019-11-21 14:22:42 +00:00
|
|
|
self.auths = {}
|
|
|
|
|
2020-02-27 15:30:16 +00:00
|
|
|
def logged_in_headers(self, user=None, redirect_url='http://some/frontend/url'):
|
|
|
|
if user is None:
|
|
|
|
uid = self.test_uid
|
2020-05-26 19:47:41 +00:00
|
|
|
user_info = {'uid': self.test_uid}
|
2020-02-27 15:30:16 +00:00
|
|
|
else:
|
|
|
|
uid = user.uid
|
2020-05-26 19:47:41 +00:00
|
|
|
user_info = {'uid': user.uid}
|
2020-02-27 15:30:16 +00:00
|
|
|
|
|
|
|
query_string = self.user_info_to_query_string(user_info, redirect_url)
|
2020-05-31 20:49:39 +00:00
|
|
|
rv = self.app.get("/v1.0/login%s" % query_string, follow_redirects=False)
|
2020-05-31 22:01:08 +00:00
|
|
|
|
2020-02-27 15:30:16 +00:00
|
|
|
self.assertTrue(rv.status_code == 302)
|
|
|
|
self.assertTrue(str.startswith(rv.location, redirect_url))
|
|
|
|
|
|
|
|
user_model = session.query(UserModel).filter_by(uid=uid).first()
|
|
|
|
self.assertIsNotNone(user_model.display_name)
|
|
|
|
return dict(Authorization='Bearer ' + user_model.encode_auth_token().decode())
|
|
|
|
|
2020-05-30 22:43:20 +00:00
|
|
|
def load_example_data(self, use_crc_data=False, use_rrt_data=False):
|
2020-05-25 16:29:05 +00:00
|
|
|
"""use_crc_data will cause this to load the mammoth collection of documents
|
2020-05-30 22:43:20 +00:00
|
|
|
we built up developing crc, use_rrt_data will do the same for hte rrt project,
|
|
|
|
otherwise it depends on a small setup for running tests."""
|
2019-12-18 19:02:17 +00:00
|
|
|
from example_data import ExampleDataLoader
|
2019-12-30 18:15:39 +00:00
|
|
|
ExampleDataLoader.clean_db()
|
2020-05-30 22:43:20 +00:00
|
|
|
if use_crc_data:
|
2020-05-25 16:29:05 +00:00
|
|
|
ExampleDataLoader().load_all()
|
2020-05-30 22:43:20 +00:00
|
|
|
elif use_rrt_data:
|
|
|
|
ExampleDataLoader().load_rrt()
|
2020-05-25 16:29:05 +00:00
|
|
|
else:
|
|
|
|
ExampleDataLoader().load_test_data()
|
2019-12-18 19:02:17 +00:00
|
|
|
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
for user_json in self.users:
|
|
|
|
db.session.add(UserModel(**user_json))
|
|
|
|
db.session.commit()
|
|
|
|
for study_json in self.studies:
|
|
|
|
study_model = StudyModel(**study_json)
|
|
|
|
db.session.add(study_model)
|
|
|
|
StudyService._add_all_workflow_specs_to_study(study_model)
|
2020-05-25 16:29:05 +00:00
|
|
|
db.session.execute(Sequence(StudyModel.__tablename__ + '_id_seq'))
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
db.session.commit()
|
|
|
|
db.session.flush()
|
|
|
|
|
2020-01-24 14:35:14 +00:00
|
|
|
specs = session.query(WorkflowSpecModel).all()
|
|
|
|
self.assertIsNotNone(specs)
|
|
|
|
|
|
|
|
for spec in specs:
|
|
|
|
files = session.query(FileModel).filter_by(workflow_spec_id=spec.id).all()
|
|
|
|
self.assertIsNotNone(files)
|
|
|
|
self.assertGreater(len(files), 0)
|
|
|
|
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
for spec in specs:
|
|
|
|
files = session.query(FileModel).filter_by(workflow_spec_id=spec.id).all()
|
|
|
|
self.assertIsNotNone(files)
|
|
|
|
self.assertGreater(len(files), 0)
|
2020-01-24 14:35:14 +00:00
|
|
|
for file in files:
|
|
|
|
file_data = session.query(FileDataModel).filter_by(file_model_id=file.id).all()
|
|
|
|
self.assertIsNotNone(file_data)
|
|
|
|
self.assertGreater(len(file_data), 0)
|
|
|
|
|
2020-02-27 15:30:16 +00:00
|
|
|
@staticmethod
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
def load_test_spec(dir_name, master_spec=False, category_id=None):
|
2020-02-04 21:49:28 +00:00
|
|
|
"""Loads a spec into the database based on a directory in /tests/data"""
|
2020-02-11 16:11:21 +00:00
|
|
|
if session.query(WorkflowSpecModel).filter_by(id=dir_name).count() > 0:
|
2020-05-23 19:08:17 +00:00
|
|
|
return session.query(WorkflowSpecModel).filter_by(id=dir_name).first()
|
2020-02-04 21:49:28 +00:00
|
|
|
filepath = os.path.join(app.root_path, '..', 'tests', 'data', dir_name, "*")
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
return ExampleDataLoader().create_spec(id=dir_name, name=dir_name, filepath=filepath, master_spec=master_spec,
|
|
|
|
category_id=category_id)
|
2020-02-04 21:49:28 +00:00
|
|
|
|
2020-02-27 15:30:16 +00:00
|
|
|
@staticmethod
|
|
|
|
def protocol_builder_response(file_name):
|
2020-02-20 18:30:04 +00:00
|
|
|
filepath = os.path.join(app.root_path, '..', 'tests', 'data', 'pb_responses', file_name)
|
|
|
|
with open(filepath, 'r') as myfile:
|
|
|
|
data = myfile.read()
|
|
|
|
return data
|
|
|
|
|
2019-12-18 19:02:17 +00:00
|
|
|
def assert_success(self, rv, msg=""):
|
|
|
|
try:
|
|
|
|
data = json.loads(rv.get_data(as_text=True))
|
2020-02-18 21:38:56 +00:00
|
|
|
self.assertTrue(200 <= rv.status_code < 300,
|
2019-12-18 19:02:17 +00:00
|
|
|
"BAD Response: %i. \n %s" %
|
|
|
|
(rv.status_code, json.dumps(data)) + ". " + msg)
|
|
|
|
except:
|
2020-02-18 21:38:56 +00:00
|
|
|
self.assertTrue(200 <= rv.status_code < 300,
|
2019-12-18 19:02:17 +00:00
|
|
|
"BAD Response: %i." % rv.status_code + ". " + msg)
|
2020-02-18 21:38:56 +00:00
|
|
|
|
2020-03-09 19:12:40 +00:00
|
|
|
def assert_failure(self, rv, status_code=0, error_code=""):
|
2020-02-18 21:38:56 +00:00
|
|
|
self.assertFalse(200 <= rv.status_code < 300,
|
|
|
|
"Incorrect Valid Response:" + rv.status + ".")
|
2020-03-09 19:12:40 +00:00
|
|
|
if status_code != 0:
|
|
|
|
self.assertEqual(status_code, rv.status_code)
|
|
|
|
if error_code != "":
|
|
|
|
data = json.loads(rv.get_data(as_text=True))
|
|
|
|
self.assertEqual(error_code, data["code"])
|
2020-02-27 15:30:16 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def user_info_to_query_string(user_info, redirect_url):
|
|
|
|
query_string_list = []
|
|
|
|
items = user_info.items()
|
|
|
|
for key, value in items:
|
|
|
|
query_string_list.append('%s=%s' % (key, urllib.parse.quote(value)))
|
|
|
|
|
2020-05-31 20:49:39 +00:00
|
|
|
query_string_list.append('redirect_url=%s' % redirect_url)
|
2020-02-27 15:30:16 +00:00
|
|
|
|
|
|
|
return '?%s' % '&'.join(query_string_list)
|
|
|
|
|
|
|
|
|
2020-03-05 18:25:28 +00:00
|
|
|
def replace_file(self, name, file_path):
|
|
|
|
"""Replaces a stored file with the given name with the contents of the file at the given path."""
|
|
|
|
file_service = FileService()
|
|
|
|
file = open(file_path, "rb")
|
|
|
|
data = file.read()
|
|
|
|
|
|
|
|
file_model = db.session.query(FileModel).filter(FileModel.name == name).first()
|
|
|
|
noise, file_extension = os.path.splitext(file_path)
|
|
|
|
content_type = CONTENT_TYPES[file_extension[1:]]
|
|
|
|
file_service.update_file(file_model, data, content_type)
|
2020-03-19 21:13:30 +00:00
|
|
|
|
2020-05-23 19:08:17 +00:00
|
|
|
def create_user(self, uid="dhf8r", email="daniel.h.funk@gmail.com", display_name="Hoopy Frood"):
|
|
|
|
user = session.query(UserModel).filter(UserModel.uid == uid).first()
|
|
|
|
if user is None:
|
|
|
|
user = UserModel(uid=uid, email_address=email, display_name=display_name)
|
|
|
|
db.session.add(user)
|
|
|
|
db.session.commit()
|
|
|
|
return user
|
|
|
|
|
2020-06-11 20:39:00 +00:00
|
|
|
def create_study(self, uid="dhf8r", title="Beer conception in the bipedal software engineer", primary_investigator_id="lb3dp"):
|
|
|
|
study = session.query(StudyModel).filter_by(user_uid=uid).filter_by(title=title).first()
|
2020-05-23 19:08:17 +00:00
|
|
|
if study is None:
|
|
|
|
user = self.create_user(uid=uid)
|
|
|
|
study = StudyModel(title=title, protocol_builder_status=ProtocolBuilderStatus.ACTIVE,
|
2020-06-11 20:39:00 +00:00
|
|
|
user_uid=user.uid, primary_investigator_id=primary_investigator_id)
|
2020-05-23 19:08:17 +00:00
|
|
|
db.session.add(study)
|
|
|
|
db.session.commit()
|
|
|
|
return study
|
|
|
|
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
def create_workflow(self, workflow_name, study=None, category_id=None):
|
2020-05-23 19:08:17 +00:00
|
|
|
db.session.flush()
|
2020-05-25 16:29:05 +00:00
|
|
|
spec = db.session.query(WorkflowSpecModel).filter(WorkflowSpecModel.name == workflow_name).first()
|
|
|
|
if spec is None:
|
|
|
|
spec = self.load_test_spec(workflow_name, category_id=category_id)
|
2020-05-23 19:08:17 +00:00
|
|
|
if study is None:
|
|
|
|
study = self.create_study()
|
Created a "StudyService" and moved all complex logic around study manipulation out of the study api, and this service, as things were getting complicated. The Workflow Processor no longer creates the WorkflowModel, the study object handles that, and only passes the model into the workflow processor when it is ready to start the workflow.
Created a Study object (seperate from the StudyModel) that can cronstructed on request, and contains a different data structure than we store in the DB. This allows us to return underlying Categories and Workflows in a clean way.
Added a new status to workflows called "not_started", meaning we have not yet instantiated a processor or created a BPMN, they have no version yet and no stored data, just the possiblity of being started.
The Top Level Workflow or "Master" workflow is now a part of the sample data, and loaded at all times.
Removed the ability to "add a workflow to a study" and "remove a workflow from a study", a study contains all possible workflows by definition.
Example data no longer creates users or studies, it just creates the specs.
2020-03-30 12:00:16 +00:00
|
|
|
workflow_model = StudyService._create_workflow_model(study, spec)
|
2020-03-30 18:01:57 +00:00
|
|
|
return workflow_model
|
2020-03-19 21:13:30 +00:00
|
|
|
|
|
|
|
def create_reference_document(self):
|
2020-05-07 17:57:24 +00:00
|
|
|
file_path = os.path.join(app.root_path, 'static', 'reference', 'irb_documents.xlsx')
|
2020-03-19 21:13:30 +00:00
|
|
|
file = open(file_path, "rb")
|
2020-05-07 17:57:24 +00:00
|
|
|
FileService.add_reference_file(FileService.DOCUMENT_LIST,
|
2020-03-19 21:13:30 +00:00
|
|
|
binary_data=file.read(),
|
|
|
|
content_type=CONTENT_TYPES['xls'])
|
|
|
|
file.close()
|
2020-06-11 20:39:00 +00:00
|
|
|
|
|
|
|
def create_approval(
|
|
|
|
self,
|
|
|
|
study=None,
|
|
|
|
workflow=None,
|
|
|
|
approver_uid=None,
|
|
|
|
status=None,
|
|
|
|
version=None,
|
|
|
|
):
|
|
|
|
study = study or self.create_study()
|
|
|
|
workflow = workflow or self.create_workflow()
|
|
|
|
approver_uid = approver_uid or self.test_uid
|
|
|
|
status = status or ApprovalStatus.PENDING.value
|
|
|
|
version = version or 1
|
|
|
|
approval = ApprovalModel(study=study, workflow=workflow, approver_uid=approver_uid, status=status, version=version)
|
|
|
|
db.session.add(approval)
|
|
|
|
db.session.commit()
|
|
|
|
return approval
|
|
|
|
|