mirror of
https://github.com/sartography/cr-connect-workflow.git
synced 2025-02-20 11:48:16 +00:00
Merge pull request #169 from sartography/cr-connect-106-augment-eval-methods
Cr connect 106 augment eval methods
This commit is contained in:
commit
5d8fee7bc7
2
Pipfile
2
Pipfile
@ -38,7 +38,7 @@ recommonmark = "*"
|
||||
requests = "*"
|
||||
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
|
||||
sphinx = "*"
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "cr-connect-106-augment-eval"}
|
||||
#spiffworkflow = {editable = true,path="/home/kelly/sartography/SpiffWorkflow/"}
|
||||
swagger-ui-bundle = "*"
|
||||
webtest = "*"
|
||||
|
4
Pipfile.lock
generated
4
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "381d29428eb328ad6167774b510b9d818bd1505b95f50454a19f1564782326cc"
|
||||
"sha256": "afb6a541d1a9f33155f91529ad961492dceded89466aa1e02fed9901ac5eb146"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -804,7 +804,7 @@
|
||||
},
|
||||
"spiffworkflow": {
|
||||
"git": "https://github.com/sartography/SpiffWorkflow.git",
|
||||
"ref": "11ad40bbcb0fbd3c5bc1078e4989dc38b749f7f3"
|
||||
"ref": "7712830665b4419df019413ac095cb0749adb346"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
|
@ -40,7 +40,7 @@ class FactService(Script):
|
||||
else:
|
||||
details = "unknown fact type."
|
||||
|
||||
self.add_data_to_task(task, details)
|
||||
#self.add_data_to_task(task, details)
|
||||
|
||||
print(details)
|
||||
return details
|
||||
|
50
crc/scripts/ldap.py
Normal file
50
crc/scripts/ldap.py
Normal file
@ -0,0 +1,50 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
class Ldap(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID (or several) as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Examples:
|
||||
supervisor_info = ldap(supervisor_uid) // Sets the supervisor information to ldap details for the given uid.
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def set_users_info_in_task(self, task, args):
|
||||
if len(args) != 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap takes a single argument, the "
|
||||
"UID for the person we want to look up")
|
||||
uid = args[0]
|
||||
user_info_dict = {}
|
||||
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"proper_name": user_info.proper_name()
|
||||
}
|
||||
|
||||
return user_info_dict
|
@ -1,78 +0,0 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
USER_DETAILS = {
|
||||
"PIComputingID": {
|
||||
"value": "",
|
||||
"data": {
|
||||
},
|
||||
"label": "invalid uid"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class LdapLookup(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Example:
|
||||
LdapLookup PIComputingID
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
self.get_user_info(task, args)
|
||||
|
||||
def do_task(self, task, *args, **kwargs):
|
||||
args = [arg for arg in args if type(arg) == str]
|
||||
user_info = self.get_user_info(task, args)
|
||||
|
||||
user_details = copy.deepcopy(USER_DETAILS)
|
||||
user_details['PIComputingID']['value'] = user_info['uid']
|
||||
if len(user_info.keys()) > 1:
|
||||
user_details['PIComputingID']['label'] = user_info.pop('label')
|
||||
else:
|
||||
user_info.pop('uid')
|
||||
user_details['PIComputingID']['data'] = user_info
|
||||
return user_details
|
||||
|
||||
def get_user_info(self, task, args):
|
||||
if len(args) < 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap lookup script requires one argument. The "
|
||||
"UID for the person we want to look up")
|
||||
|
||||
arg = args.pop() # Extracting only one value for now
|
||||
uid = task.workflow.script_engine.evaluate_expression(task, arg)
|
||||
if not isinstance(uid, str):
|
||||
raise ApiError(code="invalid_argument",
|
||||
message="Ldap lookup script requires one 1 UID argument, of type string.")
|
||||
user_info_dict = {}
|
||||
try:
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"label": user_info.proper_name()
|
||||
}
|
||||
except:
|
||||
user_info_dict['uid'] = uid
|
||||
app.logger.error(f'Ldap lookup failed for UID {uid}')
|
||||
|
||||
return user_info_dict
|
@ -1,60 +0,0 @@
|
||||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
class LdapReplace(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID (or several) as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Examples:
|
||||
#! LdapReplace supervisor
|
||||
#! LdapReplace supervisor collaborator
|
||||
#! LdapReplace supervisor cosupervisor collaborator
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
self.set_users_info_in_task(task, args)
|
||||
|
||||
def do_task(self, task, *args, **kwargs):
|
||||
args = [arg for arg in args if type(arg) == str]
|
||||
self.set_users_info_in_task(task, args)
|
||||
|
||||
def set_users_info_in_task(self, task, args):
|
||||
if len(args) < 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap replace script requires at least one argument. The "
|
||||
"UID for the person(s) we want to look up")
|
||||
|
||||
users_info = {}
|
||||
for arg in args:
|
||||
uid = task.workflow.script_engine.evaluate_expression(task, arg)
|
||||
if not isinstance(uid, str):
|
||||
raise ApiError(code="invalid_argument",
|
||||
message="Ldap replace script found an invalid argument, type string is required")
|
||||
user_info_dict = {}
|
||||
try:
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"proper_name": user_info.proper_name()
|
||||
}
|
||||
except:
|
||||
app.logger.error(f'Ldap replace failed for UID {uid}')
|
||||
task.data[arg] = user_info_dict
|
@ -23,6 +23,53 @@ class Script(object):
|
||||
"This is an internal error. The script you are trying to execute '%s' " % self.__class__.__name__ +
|
||||
"does must provide a validate_only option that mimics the do_task, " +
|
||||
"but does not make external calls or database updates." )
|
||||
@staticmethod
|
||||
def generate_augmented_list(task, study_id,workflow_id):
|
||||
"""
|
||||
this makes a dictionary of lambda functions that are closed over the class instance that
|
||||
They represent. This is passed into PythonScriptParser as a list of helper functions that are
|
||||
available for running. In general, they maintain the do_task call structure that they had, but
|
||||
they always return a value rather than updating the task data.
|
||||
|
||||
We may be able to remove the task for each of these calls if we are not using it other than potentially
|
||||
updating the task data.
|
||||
"""
|
||||
def make_closure(subclass,task,study_id,workflow_id):
|
||||
instance = subclass()
|
||||
return lambda *a : subclass.do_task(instance,task,study_id,workflow_id,*a)
|
||||
execlist = {}
|
||||
subclasses = Script.get_all_subclasses()
|
||||
for x in range(len(subclasses)):
|
||||
subclass = subclasses[x]
|
||||
execlist[subclass.__module__.split('.')[-1]] = make_closure(subclass,task,study_id,
|
||||
workflow_id)
|
||||
return execlist
|
||||
|
||||
@staticmethod
|
||||
def generate_augmented_validate_list(task, study_id, workflow_id):
|
||||
"""
|
||||
this makes a dictionary of lambda functions that are closed over the class instance that
|
||||
They represent. This is passed into PythonScriptParser as a list of helper functions that are
|
||||
available for running. In general, they maintain the do_task call structure that they had, but
|
||||
they always return a value rather than updating the task data.
|
||||
|
||||
We may be able to remove the task for each of these calls if we are not using it other than potentially
|
||||
updating the task data.
|
||||
"""
|
||||
|
||||
def make_closure_validate(subclass,task,study_id,workflow_id):
|
||||
instance = subclass()
|
||||
return lambda *a : subclass.do_task_validate_only(instance,task,study_id,workflow_id,*a)
|
||||
execlist = {}
|
||||
subclasses = Script.get_all_subclasses()
|
||||
for x in range(len(subclasses)):
|
||||
subclass = subclasses[x]
|
||||
execlist[subclass.__module__.split('.')[-1]] = make_closure_validate(subclass,task,study_id,
|
||||
workflow_id)
|
||||
return execlist
|
||||
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_all_subclasses():
|
||||
|
@ -8,7 +8,7 @@ from crc.scripts.script import Script
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.protocol_builder import ProtocolBuilderService
|
||||
from crc.services.study_service import StudyService
|
||||
|
||||
from box import Box
|
||||
|
||||
class StudyInfo(Script):
|
||||
"""Please see the detailed description that is provided below. """
|
||||
@ -149,11 +149,11 @@ Returns information specific to the protocol.
|
||||
|
||||
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
"""For validation only, pretend no results come back from pb"""
|
||||
self.check_args(args)
|
||||
self.check_args(args,2)
|
||||
# Assure the reference file exists (a bit hacky, but we want to raise this error early, and cleanly.)
|
||||
FileService.get_reference_file_data(FileService.DOCUMENT_LIST)
|
||||
FileService.get_reference_file_data(FileService.INVESTIGATOR_LIST)
|
||||
data = {
|
||||
data = Box({
|
||||
"study":{
|
||||
"info": {
|
||||
"id": 12,
|
||||
@ -195,38 +195,50 @@ Returns information specific to the protocol.
|
||||
'id': 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.add_data_to_task(task=task, data=data["study"])
|
||||
self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
|
||||
})
|
||||
if args[0]=='documents':
|
||||
return StudyService().get_documents_status(study_id)
|
||||
return data['study'][args[0]]
|
||||
#self.add_data_to_task(task=task, data=data["study"])
|
||||
#self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
|
||||
|
||||
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
self.check_args(args)
|
||||
|
||||
self.check_args(args,2)
|
||||
prefix = None
|
||||
if len(args) > 1:
|
||||
prefix = args[1]
|
||||
cmd = args[0]
|
||||
study_info = {}
|
||||
if self.__class__.__name__ in task.data:
|
||||
study_info = task.data[self.__class__.__name__]
|
||||
|
||||
# study_info = {}
|
||||
# if self.__class__.__name__ in task.data:
|
||||
# study_info = task.data[self.__class__.__name__]
|
||||
retval = None
|
||||
if cmd == 'info':
|
||||
study = session.query(StudyModel).filter_by(id=study_id).first()
|
||||
schema = StudySchema()
|
||||
self.add_data_to_task(task, {cmd: schema.dump(study)})
|
||||
retval = schema.dump(study)
|
||||
if cmd == 'investigators':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id)})
|
||||
retval = StudyService().get_investigators(study_id)
|
||||
if cmd == 'roles':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id, all=True)})
|
||||
retval = StudyService().get_investigators(study_id, all=True)
|
||||
if cmd == 'details':
|
||||
self.add_data_to_task(task, {cmd: self.pb.get_study_details(study_id)})
|
||||
retval = self.pb.get_study_details(study_id)
|
||||
if cmd == 'approvals':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_approvals(study_id)})
|
||||
retval = StudyService().get_approvals(study_id)
|
||||
if cmd == 'documents':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_documents_status(study_id)})
|
||||
retval = StudyService().get_documents_status(study_id)
|
||||
if cmd == 'protocol':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_protocol(study_id)})
|
||||
retval = StudyService().get_protocol(study_id)
|
||||
if isinstance(retval,dict) and prefix is not None:
|
||||
return Box({x:retval[x] for x in retval.keys() if x[:len(prefix)] == prefix})
|
||||
elif isinstance(retval,dict):
|
||||
return Box(retval)
|
||||
else:
|
||||
return retval
|
||||
|
||||
|
||||
def check_args(self, args):
|
||||
if len(args) != 1 or (args[0] not in StudyInfo.type_options):
|
||||
|
||||
def check_args(self, args, maxlen=1):
|
||||
if len(args) < 1 or len(args) > maxlen or (args[0] not in StudyInfo.type_options):
|
||||
raise ApiError(code="missing_argument",
|
||||
message="The StudyInfo script requires a single argument which must be "
|
||||
"one of %s" % ",".join(StudyInfo.type_options))
|
||||
|
@ -17,6 +17,7 @@ from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser
|
||||
from SpiffWorkflow.exceptions import WorkflowTaskExecException
|
||||
from SpiffWorkflow.specs import WorkflowSpec
|
||||
|
||||
import crc
|
||||
from crc import session, app
|
||||
from crc.api.common import ApiError
|
||||
from crc.models.file import FileDataModel, FileModel, FileType
|
||||
@ -28,64 +29,71 @@ from crc import app
|
||||
|
||||
class CustomBpmnScriptEngine(BpmnScriptEngine):
|
||||
"""This is a custom script processor that can be easily injected into Spiff Workflow.
|
||||
Rather than execute arbitrary code, this assumes the script references a fully qualified python class
|
||||
such as myapp.RandomFact. """
|
||||
It will execute python code read in from the bpmn. It will also make any scripts in the
|
||||
scripts directory available for execution. """
|
||||
|
||||
def execute(self, task: SpiffTask, script, data):
|
||||
"""
|
||||
Functions in two modes.
|
||||
1. If the command is proceeded by #! then this is assumed to be a python script, and will
|
||||
attempt to load that python module and execute the do_task method on that script. Scripts
|
||||
must be located in the scripts package and they must extend the script.py class.
|
||||
2. If not proceeded by the #! this will attempt to execute the script directly and assumes it is
|
||||
valid Python.
|
||||
"""
|
||||
# Shlex splits the whole string while respecting double quoted strings within
|
||||
if not script.startswith('#!'):
|
||||
try:
|
||||
super().execute(task, script, data)
|
||||
except SyntaxError as e:
|
||||
raise ApiError.from_task('syntax_error',
|
||||
f'If you are running a pre-defined script, please'
|
||||
f' proceed the script with "#!", otherwise this is assumed to be'
|
||||
f' pure python: {script}, {e.msg}', task=task)
|
||||
else:
|
||||
self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
|
||||
|
||||
def run_predefined_script(self, task: SpiffTask, script, data):
|
||||
commands = shlex.split(script)
|
||||
path_and_command = commands[0].rsplit(".", 1)
|
||||
if len(path_and_command) == 1:
|
||||
module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
|
||||
class_name = path_and_command[0]
|
||||
study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
else:
|
||||
module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
|
||||
class_name = path_and_command[1]
|
||||
workflow_id = None
|
||||
|
||||
try:
|
||||
mod = __import__(module_name, fromlist=[class_name])
|
||||
klass = getattr(mod, class_name)
|
||||
study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
else:
|
||||
workflow_id = None
|
||||
|
||||
if not isinstance(klass(), Script):
|
||||
raise ApiError.from_task("invalid_script",
|
||||
"This is an internal error. The script '%s:%s' you called " %
|
||||
(module_name, class_name) +
|
||||
"does not properly implement the CRC Script class.",
|
||||
task=task)
|
||||
if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
|
||||
"""If this is running a validation, and not a normal process, then we want to
|
||||
mimic running the script, but not make any external calls or database changes."""
|
||||
klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
|
||||
augmentMethods = Script.generate_augmented_validate_list(task, study_id, workflow_id)
|
||||
else:
|
||||
klass().do_task(task, study_id, workflow_id, *commands[1:])
|
||||
except ModuleNotFoundError:
|
||||
raise ApiError.from_task("invalid_script",
|
||||
"Unable to locate Script: '%s:%s'" % (module_name, class_name),
|
||||
task=task)
|
||||
augmentMethods = Script.generate_augmented_list(task, study_id, workflow_id)
|
||||
|
||||
super().execute(task, script, data, externalMethods=augmentMethods)
|
||||
except SyntaxError as e:
|
||||
raise ApiError('syntax_error',
|
||||
f'Something is wrong with your python script '
|
||||
f'please correct the following:'
|
||||
f' {script}, {e.msg}')
|
||||
except NameError as e:
|
||||
raise ApiError('name_error',
|
||||
f'something you are referencing does not exist:'
|
||||
f' {script}, {e.name}')
|
||||
|
||||
# else:
|
||||
# self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
|
||||
|
||||
# def run_predefined_script(self, task: SpiffTask, script, data):
|
||||
# commands = shlex.split(script)
|
||||
# path_and_command = commands[0].rsplit(".", 1)
|
||||
# if len(path_and_command) == 1:
|
||||
# module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
|
||||
# class_name = path_and_command[0]
|
||||
# else:
|
||||
# module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
|
||||
# class_name = path_and_command[1]
|
||||
# try:
|
||||
# mod = __import__(module_name, fromlist=[class_name])
|
||||
# klass = getattr(mod, class_name)
|
||||
# study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
# if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
# workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
# else:
|
||||
# workflow_id = None
|
||||
#
|
||||
# if not isinstance(klass(), Script):
|
||||
# raise ApiError.from_task("invalid_script",
|
||||
# "This is an internal error. The script '%s:%s' you called " %
|
||||
# (module_name, class_name) +
|
||||
# "does not properly implement the CRC Script class.",
|
||||
# task=task)
|
||||
# if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
|
||||
# """If this is running a validation, and not a normal process, then we want to
|
||||
# mimic running the script, but not make any external calls or database changes."""
|
||||
# klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
|
||||
# else:
|
||||
# klass().do_task(task, study_id, workflow_id, *commands[1:])
|
||||
# except ModuleNotFoundError:
|
||||
# raise ApiError.from_task("invalid_script",
|
||||
# "Unable to locate Script: '%s:%s'" % (module_name, class_name),
|
||||
# task=task)
|
||||
|
||||
def evaluate_expression(self, task, expression):
|
||||
"""
|
||||
@ -180,10 +188,10 @@ class WorkflowProcessor(object):
|
||||
bpmn_workflow = BpmnWorkflow(spec, script_engine=self._script_engine)
|
||||
bpmn_workflow.data[WorkflowProcessor.STUDY_ID_KEY] = workflow_model.study_id
|
||||
bpmn_workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY] = validate_only
|
||||
try:
|
||||
bpmn_workflow.do_engine_steps()
|
||||
except WorkflowException as we:
|
||||
raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
|
||||
#try:
|
||||
bpmn_workflow.do_engine_steps()
|
||||
# except WorkflowException as we:
|
||||
# raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
|
||||
return bpmn_workflow
|
||||
|
||||
def save(self):
|
||||
|
@ -212,7 +212,8 @@
|
||||
<bpmn:scriptTask id="Activity_10nxpt2" name="Load Study Details">
|
||||
<bpmn:incoming>SequenceFlow_1r3yrhy</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_09h1imz</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_PBMultiSiteCheckQ12" name="PB Multi-Site Check Q12" camunda:decisionRef="Decision_core_info_multi_site_q12">
|
||||
<bpmn:incoming>Flow_09h1imz</bpmn:incoming>
|
||||
|
@ -453,7 +453,7 @@ Indicate all the possible formats in which you will transmit your data outside o
|
||||
<bpmn:incoming>SequenceFlow_0k2r83n</bpmn:incoming>
|
||||
<bpmn:incoming>SequenceFlow_0t6xl9i</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_16kyite</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate NEW_DSP_template.docx Study_DataSecurityPlan</bpmn:script>
|
||||
<bpmn:script>complete_template('NEW_DSP_template.docx','Study_DataSecurityPlan')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:manualTask id="Task_0q6ir2l" name="View Instructions">
|
||||
<bpmn:documentation>##### Instructions
|
||||
|
@ -53,12 +53,13 @@
|
||||
<bpmn:scriptTask id="Activity_0a14x7j" name="Load Approvals">
|
||||
<bpmn:incoming>Flow_0c7ryff</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_142jtxs</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo approvals</bpmn:script>
|
||||
<bpmn:script>StudyInfo['approvals'] = study_info('approvals')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:scriptTask id="Activity_1aju60t" name="Load Documents">
|
||||
<bpmn:incoming>Flow_1k3su2q</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0c7ryff</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_142jtxs" sourceRef="Activity_0a14x7j" targetRef="Activity_DisplayDocsAndApprovals" />
|
||||
<bpmn:sequenceFlow id="Flow_0c7ryff" sourceRef="Activity_1aju60t" targetRef="Activity_0a14x7j" />
|
||||
|
@ -36,7 +36,8 @@
|
||||
<bpmn:scriptTask id="ScriptTask_1fn00ox" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1dhb8f4</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1uzcl1f</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1uzcl1f" sourceRef="ScriptTask_1fn00ox" targetRef="Task_SupplementIDE" />
|
||||
<bpmn:exclusiveGateway id="ExclusiveGateway_1fib89p" name="IS_IDE = True and Number Provided? ">
|
||||
|
@ -217,7 +217,8 @@ Protocol Owner: **(need to insert value here)**</bpmn:documentation>
|
||||
<bpmn:scriptTask id="Activity_LoadDocuments" name="Load Documents">
|
||||
<bpmn:incoming>SequenceFlow_1dexemq</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1x9d2mo</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
@ -12,7 +12,8 @@
|
||||
<bpmn:scriptTask id="ScriptTask_LoadIRBDetails" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1dhb8f4</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1uzcl1f</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1uzcl1f" sourceRef="ScriptTask_LoadIRBDetails" targetRef="Task_SupplementIDE" />
|
||||
<bpmn:businessRuleTask id="Task_SupplementIDE" name="Current IND Status" camunda:decisionRef="decision_ind_check">
|
||||
|
@ -8,7 +8,8 @@
|
||||
<bpmn:scriptTask id="ScriptTask_02924vs" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1fmyo77</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_18nr0gf</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1fmyo77" sourceRef="StartEvent_1" targetRef="ScriptTask_02924vs" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_18nr0gf" sourceRef="ScriptTask_02924vs" targetRef="Activity_FromIRB-API" />
|
||||
|
@ -7,7 +7,8 @@
|
||||
<bpmn:scriptTask id="ScriptTask_LoadPersonnel" name="Load IRB Personnel">
|
||||
<bpmn:incoming>Flow_0kcrx5l</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1dcsioh</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_1qor16n">
|
||||
<bpmn:documentation>## The following information was gathered:
|
||||
|
@ -598,7 +598,7 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
|
||||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_11uqavk</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0aqgwvu</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate ResearchRampUpPlan.docx RESEARCH_RAMPUP</bpmn:script>
|
||||
<bpmn:script>complete_template('ResearchRampUpPlan.docx','RESEARCH_RAMPUP')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_0aqgwvu" sourceRef="Activity_GenerateRRP" targetRef="Activity_AcknowledgePlanReview" />
|
||||
<bpmn:sequenceFlow id="Flow_0j4rs82" sourceRef="Activity_SubmitPlan" targetRef="Activity_0absozl" />
|
||||
@ -755,7 +755,7 @@ Notify the Area Monitor for
|
||||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0j4rs82</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_07ge8uf</bpmn:outgoing>
|
||||
<bpmn:script>#!RequestApproval ApprvlApprvr1 ApprvlApprvr2</bpmn:script>
|
||||
<bpmn:script>request_approval('ApprvlApprvr1','ApprvlApprvr2')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:scriptTask id="Activity_1u58hox" name="Update Request">
|
||||
<bpmn:documentation>#### Script Task
|
||||
@ -764,7 +764,7 @@ This step is internal to the system and do not require and user interaction</bpm
|
||||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_16y8glw</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0uc4o6c</bpmn:outgoing>
|
||||
<bpmn:script>#! UpdateStudy title:PIComputingID.label pi:PIComputingID.value</bpmn:script>
|
||||
<bpmn:script>update_study('title:PIComputingID.label','pi:PIComputingID.value')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:userTask id="PersonnelSchedule" name="Upload Weekly Personnel Schedule(s)" camunda:formKey="Personnel Weekly Schedule">
|
||||
<bpmn:documentation>#### Weekly Personnel Schedule(s)
|
||||
|
@ -11,7 +11,8 @@
|
||||
<bpmn:scriptTask id="Task_Load_Requirements" name="Load Documents From PB">
|
||||
<bpmn:incoming>SequenceFlow_1ees8ka</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_17ct47v</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_1yqy50i" name="Enter Core Info " camunda:decisionRef="enter_core_info">
|
||||
<bpmn:incoming>Flow_1m8285h</bpmn:incoming>
|
||||
@ -62,7 +63,8 @@
|
||||
<bpmn:scriptTask id="Activity_0f295la" name="Load Details from PB">
|
||||
<bpmn:incoming>Flow_0pwtiqm</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0eq6px2</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_0ahlc3u" name="IDE Supplement" camunda:decisionRef="decision_ide_menu_check">
|
||||
<bpmn:incoming>Flow_14ce1d7</bpmn:incoming>
|
||||
@ -91,7 +93,8 @@
|
||||
<bpmn:scriptTask id="Activity_0g3qa1c" name="Load Personnel from PB">
|
||||
<bpmn:incoming>Flow_1qyrmzn</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0vo6ul1</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1ybicki" sourceRef="Activity_13ep6ar" targetRef="Event_135x8jg" />
|
||||
<bpmn:businessRuleTask id="Activity_13ep6ar" name="Personnel" camunda:decisionRef="personnel">
|
||||
|
@ -27,7 +27,7 @@
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>SequenceFlow_1i7hk1a</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_11c35oq</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate Letter.docx AD_CoCApp</bpmn:script>
|
||||
<bpmn:script>complete_template('Letter.docx','AD_CoCApp')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_0evb22x">
|
||||
<bpmn:incoming>SequenceFlow_11c35oq</bpmn:incoming>
|
||||
|
@ -20,7 +20,7 @@ Email content to be delivered to {{ ApprvlApprvr1 }}
|
||||
---</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_08n2npe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1xlrgne</bpmn:outgoing>
|
||||
<bpmn:script>#! Email "Camunda Email Subject" ApprvlApprvr1 PIComputingID</bpmn:script>
|
||||
<bpmn:script>email("Camunda Email Subject",'ApprvlApprvr1','PIComputingID')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1synsig" sourceRef="StartEvent_1" targetRef="Activity_1l9vih3" />
|
||||
<bpmn:sequenceFlow id="Flow_1xlrgne" sourceRef="Activity_0s5v97n" targetRef="Event_0izrcj4" />
|
||||
|
@ -11,7 +11,7 @@
|
||||
<bpmn:scriptTask id="Invalid_Script_Task" name="An Invalid Script Reference">
|
||||
<bpmn:incoming>SequenceFlow_1pnq3kg</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_12pf6um</bpmn:outgoing>
|
||||
<bpmn:script>#! NoSuchScript withArg1</bpmn:script>
|
||||
<bpmn:script>no_such_script('withArg1')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_12pf6um" sourceRef="Invalid_Script_Task" targetRef="EndEvent_063bpg6" />
|
||||
</bpmn:process>
|
||||
|
@ -10,7 +10,8 @@
|
||||
<bpmn:scriptTask id="Activity_0s5v97n" name="Ldap Replace">
|
||||
<bpmn:incoming>Flow_08n2npe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1xlrgne</bpmn:outgoing>
|
||||
<bpmn:script>#! LdapReplace Supervisor Investigator</bpmn:script>
|
||||
<bpmn:script>Supervisor = ldap(Supervisor)
|
||||
Investigator = ldap(Investigator)</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1synsig" sourceRef="StartEvent_1" targetRef="Activity_1l9vih3" />
|
||||
<bpmn:sequenceFlow id="Flow_1xlrgne" sourceRef="Activity_0s5v97n" targetRef="Activity_0f78ek5" />
|
||||
@ -33,6 +34,10 @@
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0tad5ma">
|
||||
<bpmndi:BPMNEdge id="Flow_11e7jgz_di" bpmnElement="Flow_11e7jgz">
|
||||
<di:waypoint x="720" y="117" />
|
||||
<di:waypoint x="802" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_08n2npe_di" bpmnElement="Flow_08n2npe">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="450" y="117" />
|
||||
@ -45,22 +50,18 @@
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_11e7jgz_di" bpmnElement="Flow_11e7jgz">
|
||||
<di:waypoint x="720" y="117" />
|
||||
<di:waypoint x="802" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0izrcj4_di" bpmnElement="Event_0izrcj4">
|
||||
<dc:Bounds x="802" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_04imfm6_di" bpmnElement="Activity_0s5v97n">
|
||||
<dc:Bounds x="450" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0xugr62_di" bpmnElement="Activity_1l9vih3">
|
||||
<dc:Bounds x="270" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0izrcj4_di" bpmnElement="Event_0izrcj4">
|
||||
<dc:Bounds x="802" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_17h05g6_di" bpmnElement="Activity_0f78ek5">
|
||||
<dc:Bounds x="620" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
|
@ -29,7 +29,8 @@
|
||||
<bpmn:scriptTask id="Task_1v0e2zu" name="Load Personnel">
|
||||
<bpmn:incoming>Flow_0t6p1sb</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1p568pp</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
@ -11,7 +11,7 @@
|
||||
<bpmn:sequenceFlow id="Flow_0ugjw69" sourceRef="MultiInstanceTask" targetRef="Event_End" />
|
||||
<bpmn:userTask id="MultiInstanceTask" name="Gather more information" camunda:formKey="GetEmail">
|
||||
<bpmn:documentation># Please provide addtional information about:
|
||||
## Investigator ID: {{investigator.user_id}}
|
||||
## Investigator ID: {{investigator.user_id}}
|
||||
## Role: {{investigator.type_full}}</bpmn:documentation>
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
@ -29,7 +29,8 @@
|
||||
<bpmn:scriptTask id="Task_1v0e2zu" name="Load Personnel">
|
||||
<bpmn:incoming>Flow_0t6p1sb</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1p568pp</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
@ -132,7 +132,7 @@ Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>SequenceFlow_0641sh6</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_0t29gjo</bpmn:outgoing>
|
||||
<bpmn:script>#! FactService</bpmn:script>
|
||||
<bpmn:script>FactService = fact_service()</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_0u1cgrf">
|
||||
<bpmn:documentation># Great Job!
|
||||
|
@ -8,12 +8,19 @@
|
||||
<bpmn:scriptTask id="Task_Script_Load_Study_Details" name="Load Study Info">
|
||||
<bpmn:incoming>SequenceFlow_1nfe5m9</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1bqiin0</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo info</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['info'] = study_info('info')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1bqiin0" sourceRef="Task_Script_Load_Study_Details" targetRef="EndEvent_171dj09" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1bqiin0" sourceRef="Task_Script_Load_Study_Details" targetRef="Activity_0w91u9s" />
|
||||
<bpmn:endEvent id="EndEvent_171dj09">
|
||||
<bpmn:incoming>SequenceFlow_1bqiin0</bpmn:incoming>
|
||||
<bpmn:incoming>Flow_0ochvmi</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0ochvmi" sourceRef="Activity_0w91u9s" targetRef="EndEvent_171dj09" />
|
||||
<bpmn:scriptTask id="Activity_0w91u9s" name="StudyInfo as Script">
|
||||
<bpmn:incoming>SequenceFlow_1bqiin0</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0ochvmi</bpmn:outgoing>
|
||||
<bpmn:script>study = study_info('info','p')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0exnnpv">
|
||||
@ -29,10 +36,17 @@
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_1bqiin0_di" bpmnElement="SequenceFlow_1bqiin0">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="402" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="EndEvent_171dj09_di" bpmnElement="EndEvent_171dj09">
|
||||
<dc:Bounds x="402" y="99" width="36" height="36" />
|
||||
<dc:Bounds x="622" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_0ochvmi_di" bpmnElement="Flow_0ochvmi">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="622" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Activity_1wtk4bb_di" bpmnElement="Activity_0w91u9s">
|
||||
<dc:Bounds x="430" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
|
@ -11,7 +11,8 @@
|
||||
<bpmn:scriptTask id="Task_Load_Requirements" name="Load Required Documents From PM">
|
||||
<bpmn:incoming>SequenceFlow_1ees8ka</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_17ct47v</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_1yqy50i" name="Enter Core Info " camunda:decisionRef="enter_core_info">
|
||||
<bpmn:incoming>Flow_1m8285h</bpmn:incoming>
|
||||
|
@ -1,7 +1,8 @@
|
||||
from tests.base_test import BaseTest
|
||||
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
from crc.scripts.ldap_replace import LdapReplace
|
||||
from crc.scripts.ldap import Ldap
|
||||
from crc.api.common import ApiError
|
||||
from crc import db, mail
|
||||
|
||||
|
||||
@ -14,60 +15,19 @@ class TestLdapLookupScript(BaseTest):
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
task.data = {
|
||||
'PIComputingID': 'dhf8r'
|
||||
}
|
||||
script = Ldap()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "dhf8r")
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
|
||||
self.assertEqual(task.data['PIComputingID']['display_name'], 'Dan Funk')
|
||||
self.assertEqual(task.data['PIComputingID']['given_name'], 'Dan')
|
||||
self.assertEqual(task.data['PIComputingID']['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(task.data['PIComputingID']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['PIComputingID']['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(task.data['PIComputingID']['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(task.data['PIComputingID']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['PIComputingID']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['PIComputingID']['uid'], 'dhf8r')
|
||||
self.assertEqual(task.data['PIComputingID']['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
def test_get_existing_users_details(self):
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('empty_workflow')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
task.data = {
|
||||
'supervisor': 'dhf8r',
|
||||
'investigator': 'lb3dp'
|
||||
}
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "supervisor", "investigator")
|
||||
|
||||
self.assertEqual(task.data['supervisor']['display_name'], 'Dan Funk')
|
||||
self.assertEqual(task.data['supervisor']['given_name'], 'Dan')
|
||||
self.assertEqual(task.data['supervisor']['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(task.data['supervisor']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['supervisor']['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(task.data['supervisor']['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(task.data['supervisor']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['supervisor']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['supervisor']['uid'], 'dhf8r')
|
||||
self.assertEqual(task.data['supervisor']['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
self.assertEqual(task.data['investigator']['display_name'], 'Laura Barnes')
|
||||
self.assertEqual(task.data['investigator']['given_name'], 'Laura')
|
||||
self.assertEqual(task.data['investigator']['email_address'], 'lb3dp@virginia.edu')
|
||||
self.assertEqual(task.data['investigator']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['investigator']['title'], 'E0:Associate Professor of Systems and Information Engineering')
|
||||
self.assertEqual(task.data['investigator']['department'], 'E0:EN-Eng Sys and Environment')
|
||||
self.assertEqual(task.data['investigator']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['investigator']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['investigator']['uid'], 'lb3dp')
|
||||
self.assertEqual(task.data['investigator']['proper_name'], 'Laura Barnes - (lb3dp)')
|
||||
self.assertEqual(user_details['display_name'], 'Dan Funk')
|
||||
self.assertEqual(user_details['given_name'], 'Dan')
|
||||
self.assertEqual(user_details['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(user_details['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(user_details['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(user_details['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(user_details['affiliation'], 'faculty')
|
||||
self.assertEqual(user_details['sponsor_type'], 'Staff')
|
||||
self.assertEqual(user_details['uid'], 'dhf8r')
|
||||
self.assertEqual(user_details['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
def test_get_invalid_user_details(self):
|
||||
self.load_example_data()
|
||||
@ -80,10 +40,10 @@ class TestLdapLookupScript(BaseTest):
|
||||
'PIComputingID': 'rec3z'
|
||||
}
|
||||
|
||||
script = LdapReplace()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
script = Ldap()
|
||||
with(self.assertRaises(ApiError)):
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
|
||||
self.assertEqual(task.data['PIComputingID'], {})
|
||||
|
||||
def test_bpmn_task_receives_user_details(self):
|
||||
workflow = self.create_workflow('ldap_replace')
|
||||
|
@ -89,8 +89,8 @@ class TestWorkflowSpecValidation(BaseTest):
|
||||
self.load_example_data()
|
||||
errors = self.validate_workflow("invalid_script")
|
||||
self.assertEqual(2, len(errors))
|
||||
self.assertEqual("error_loading_workflow", errors[0]['code'])
|
||||
self.assertTrue("NoSuchScript" in errors[0]['message'])
|
||||
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
||||
#self.assertTrue("NoSuchScript" in errors[0]['message'])
|
||||
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
|
||||
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
|
||||
self.assertEqual("invalid_script.bpmn", errors[0]['file_name'])
|
||||
@ -99,7 +99,7 @@ class TestWorkflowSpecValidation(BaseTest):
|
||||
self.load_example_data()
|
||||
errors = self.validate_workflow("invalid_script2")
|
||||
self.assertEqual(2, len(errors))
|
||||
self.assertEqual("error_loading_workflow", errors[0]['code'])
|
||||
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
||||
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
|
||||
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
|
||||
self.assertEqual("invalid_script2.bpmn", errors[0]['file_name'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user