Merge branch 'dev' into cr-workflow-108

This commit is contained in:
Kelly McDonald 2020-08-12 10:50:19 -04:00
commit 7bfcdd53cd
18 changed files with 1123 additions and 76 deletions

View File

@ -1082,6 +1082,7 @@ components:
example: "2019-12-25T09:12:33.001Z"
primary_investigator_id:
type: string
x-nullable: true
example: dhf8r
user_uid:
type: string
@ -1092,18 +1093,16 @@ components:
example: done
sponsor:
type: string
x-nullable: true
example: "Sartography Pharmaceuticals"
ind_number:
type: string
x-nullable: true
example: "27b-6-42"
hsr_number:
type: string
x-nullable: true
example: "27b-6-1212"
categories:
type: array
items:
$ref: "#/components/schemas/WorkflowSpecCategory"
WorkflowSpec:
properties:
id:

View File

@ -6,7 +6,7 @@ from sqlalchemy.exc import IntegrityError
from crc import session
from crc.api.common import ApiError, ApiErrorSchema
from crc.models.protocol_builder import ProtocolBuilderStatus
from crc.models.study import Study, StudyModel, StudySchema, StudyStatus
from crc.models.study import Study, StudyModel, StudySchema, StudyForUpdateSchema, StudyStatus
from crc.services.study_service import StudyService
from crc.services.user_service import UserService
@ -41,10 +41,12 @@ def update_study(study_id, body):
if study_model is None:
raise ApiError('unknown_study', 'The study "' + study_id + '" is not recognized.')
study: Study = StudySchema().load(body)
study: Study = StudyForUpdateSchema().load(body)
study.update_model(study_model)
session.add(study_model)
session.commit()
# Need to reload the full study to return it to the frontend
study = StudyService.get_study(study_id)
return StudySchema().dump(study)

View File

@ -37,6 +37,9 @@ class Task(object):
# Custom properties and validations defined in Camunda form fields #
##########################################################################
# Custom task title
PROP_EXTENSIONS_TITLE = "display_name"
# Repeating form section
PROP_OPTIONS_REPEAT = "repeat"

View File

@ -13,6 +13,7 @@ from crc.models.file import FileModel, SimpleFileSchema, FileSchema
from crc.models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudy
from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowState, WorkflowStatus, WorkflowSpecModel, \
WorkflowModel
from crc.services.user_service import UserService
class StudyStatus(enum.Enum):
@ -28,6 +29,11 @@ class IrbStatus(enum.Enum):
hsr_assigned = 'hsr number assigned'
class StudyEventType(enum.Enum):
user = 'user'
automatic = 'automatic'
class StudyModel(db.Model):
__tablename__ = 'study'
id = db.Column(db.Integer, primary_key=True)
@ -44,6 +50,8 @@ class StudyModel(db.Model):
requirements = db.Column(db.ARRAY(db.Integer), nullable=True)
on_hold = db.Column(db.Boolean, default=False)
enrollment_date = db.Column(db.DateTime(timezone=True), nullable=True)
# events = db.relationship("TaskEventModel")
events_history = db.relationship("StudyEvent", cascade="all, delete, delete-orphan")
def update_from_protocol_builder(self, pbs: ProtocolBuilderStudy):
self.hsr_number = pbs.HSRNUMBER
@ -60,6 +68,18 @@ class StudyModel(db.Model):
self.status = StudyStatus.hold
class StudyEvent(db.Model):
__tablename__ = 'study_event'
id = db.Column(db.Integer, primary_key=True)
study_id = db.Column(db.Integer, db.ForeignKey(StudyModel.id), nullable=False)
study = db.relationship(StudyModel, back_populates='events_history')
create_date = db.Column(db.DateTime(timezone=True), default=func.now())
status = db.Column(db.Enum(StudyStatus))
comment = db.Column(db.String, default='')
event_type = db.Column(db.Enum(StudyEventType))
user_uid = db.Column(db.String, db.ForeignKey('user.uid'), nullable=True)
class WorkflowMetadata(object):
def __init__(self, id, name = None, display_name = None, description = None, spec_version = None,
category_id = None, category_display_name = None, state: WorkflowState = None,
@ -128,15 +148,16 @@ class CategorySchema(ma.Schema):
class Study(object):
def __init__(self, title, last_updated, primary_investigator_id, user_uid,
id=None, status=None, irb_status=None,
id=None, status=None, irb_status=None, comment="",
sponsor="", hsr_number="", ind_number="", categories=[],
files=[], approvals=[], enrollment_date=None, **argsv):
files=[], approvals=[], enrollment_date=None, events_history=[], **argsv):
self.id = id
self.user_uid = user_uid
self.title = title
self.last_updated = last_updated
self.status = status
self.irb_status = irb_status
self.comment = comment
self.primary_investigator_id = primary_investigator_id
self.sponsor = sponsor
self.hsr_number = hsr_number
@ -146,11 +167,13 @@ class Study(object):
self.warnings = []
self.files = files
self.enrollment_date = enrollment_date
self.events_history = events_history
@classmethod
def from_model(cls, study_model: StudyModel):
id = study_model.id # Just read some value, in case the dict expired, otherwise dict may be empty.
args = dict((k, v) for k, v in study_model.__dict__.items() if not k.startswith('_'))
args['events_history'] = study_model.events_history # For some reason this attribute is not picked up
instance = cls(**args)
return instance
@ -165,18 +188,15 @@ class Study(object):
if status == StudyStatus.open_for_enrollment:
study_model.enrollment_date = self.enrollment_date
# change = {
# 'status': ProtocolBuilderStatus(self.protocol_builder_status).value,
# 'comment': '' if not hasattr(self, 'comment') else self.comment,
# 'date': str(datetime.datetime.now())
# }
# if study_model.changes_history:
# changes_history = json.loads(study_model.changes_history)
# changes_history.append(change)
# else:
# changes_history = [change]
# study_model.changes_history = json.dumps(changes_history)
study_event = StudyEvent(
study=study_model,
status=status,
comment='' if not hasattr(self, 'comment') else self.comment,
event_type=StudyEventType.user,
user_uid=UserService.current_user().uid if UserService.has_user() else None,
)
db.session.add(study_event)
db.session.commit()
def model_args(self):
@ -207,6 +227,15 @@ class StudyForUpdateSchema(ma.Schema):
return Study(**data)
class StudyEventSchema(ma.Schema):
id = fields.Integer(required=False)
create_date = fields.DateTime()
status = EnumField(StudyStatus, by_value=True)
comment = fields.String(allow_none=True)
event_type = EnumField(StudyEvent, by_value=True)
class StudySchema(ma.Schema):
id = fields.Integer(required=False, allow_none=True)
@ -220,11 +249,13 @@ class StudySchema(ma.Schema):
files = fields.List(fields.Nested(FileSchema), dump_only=True)
approvals = fields.List(fields.Nested('ApprovalSchema'), dump_only=True)
enrollment_date = fields.Date(allow_none=True)
events_history = fields.List(fields.Nested('StudyEventSchema'), dump_only=True)
class Meta:
model = Study
additional = ["id", "title", "last_updated", "primary_investigator_id", "user_uid",
"sponsor", "ind_number", "approvals", "files", "enrollment_date"]
"sponsor", "ind_number", "approvals", "files", "enrollment_date",
"events_history"]
unknown = INCLUDE
@marshmallow.post_load

View File

@ -2,6 +2,7 @@ import json
from crc import session
from crc.api.common import ApiError
from crc.models.protocol_builder import ProtocolBuilderInvestigatorType
from crc.models.study import StudyModel, StudySchema
from crc.models.workflow import WorkflowStatus
from crc.scripts.script import Script
@ -30,7 +31,7 @@ class StudyInfo(Script):
},
"investigators": {
'PI': {
'label': 'Primary Investigator',
'label': ProtocolBuilderInvestigatorType.PI.value,
'display': 'Always',
'unique': 'Yes',
'user_id': 'dhf8r',
@ -164,16 +165,78 @@ Returns information specific to the protocol.
"ind_number": "1234",
"inactive": False
},
"investigators":
{
"INVESTIGATORTYPE": "PI",
"INVESTIGATORTYPEFULL": "Primary Investigator",
"NETBADGEID": "dhf8r"
"investigators": {
"PI": {
"label": ProtocolBuilderInvestigatorType.PI.value,
"display": "Always",
"unique": "Yes",
"user_id": "dhf8r",
"title": "",
"display_name": "Daniel Harold Funk",
"sponsor_type": "Contractor",
"telephone_number": "0000000000",
"department": "",
"email_address": "dhf8r@virginia.edu",
"given_name": "Daniel",
"uid": "dhf8r",
"affiliation": "",
"date_cached": "2020-08-04T19:32:08.006128+00:00"
},
"SC_I": {
"label": ProtocolBuilderInvestigatorType.SC_I.value,
"display": "Always",
"unique": "Yes",
"user_id": "ajl2j",
"title": "",
"display_name": "Aaron Louie",
"sponsor_type": "Contractor",
"telephone_number": "0000000000",
"department": "",
"email_address": "ajl2j@virginia.edu",
"given_name": "Aaron",
"uid": "ajl2j",
"affiliation": "sponsored",
"date_cached": "2020-08-04T19:32:10.699666+00:00"
},
"SC_II": {
"label": ProtocolBuilderInvestigatorType.SC_II.value,
"display": "Optional",
"unique": "Yes",
"user_id": "cah3us",
"title": "",
"display_name": "Alex Herron",
"sponsor_type": "Contractor",
"telephone_number": "0000000000",
"department": "",
"email_address": "cah3us@virginia.edu",
"given_name": "Alex",
"uid": "cah3us",
"affiliation": "sponsored",
"date_cached": "2020-08-04T19:32:10.075852+00:00"
}
},
"pi": {
"PI": {
"label": ProtocolBuilderInvestigatorType.PI.value,
"display": "Always",
"unique": "Yes",
"user_id": "dhf8r",
"title": "",
"display_name": "Daniel Harold Funk",
"sponsor_type": "Contractor",
"telephone_number": "0000000000",
"department": "",
"email_address": "dhf8r@virginia.edu",
"given_name": "Daniel",
"uid": "dhf8r",
"affiliation": "",
"date_cached": "2020-08-04T19:32:08.006128+00:00"
}
},
"roles":
{
"INVESTIGATORTYPE": "PI",
"INVESTIGATORTYPEFULL": "Primary Investigator",
"INVESTIGATORTYPEFULL": ProtocolBuilderInvestigatorType.PI.value,
"NETBADGEID": "dhf8r"
},
"details":

View File

@ -8,7 +8,6 @@ from crc import app
from crc.api.common import ApiError
from crc.models.protocol_builder import ProtocolBuilderStudySchema, ProtocolBuilderRequiredDocument
class ProtocolBuilderService(object):
STUDY_URL = app.config['PB_USER_STUDIES_URL']
INVESTIGATOR_URL = app.config['PB_INVESTIGATORS_URL']

View File

@ -12,7 +12,7 @@ from crc.api.common import ApiError
from crc.models.file import FileModel, FileModelSchema, File
from crc.models.ldap import LdapSchema
from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus
from crc.models.study import StudyModel, Study, StudyStatus, Category, WorkflowMetadata
from crc.models.study import StudyModel, Study, StudyStatus, Category, WorkflowMetadata, StudyEvent
from crc.models.task_event import TaskEventModel, TaskEvent
from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowModel, WorkflowSpecModel, WorkflowState, \
WorkflowStatus
@ -53,6 +53,7 @@ class StudyService(object):
loading up and executing all the workflows in a study to calculate information."""
if not study_model:
study_model = session.query(StudyModel).filter_by(id=study_id).first()
study = Study.from_model(study_model)
study.categories = StudyService.get_categories()
workflow_metas = StudyService.__get_workflow_metas(study_id)
@ -77,9 +78,11 @@ class StudyService(object):
@staticmethod
def delete_study(study_id):
session.query(TaskEventModel).filter_by(study_id=study_id).delete()
# session.query(StudyEvent).filter_by(study_id=study_id).delete()
for workflow in session.query(WorkflowModel).filter_by(study_id=study_id):
StudyService.delete_workflow(workflow)
session.query(StudyModel).filter_by(id=study_id).delete()
study = session.query(StudyModel).filter_by(id=study_id).first()
session.delete(study)
session.commit()
@staticmethod
@ -90,6 +93,7 @@ class StudyService(object):
session.delete(dep)
session.query(TaskEventModel).filter_by(workflow_id=workflow.id).delete()
session.query(WorkflowModel).filter_by(id=workflow.id).delete()
session.commit()
@staticmethod
def get_categories():

View File

@ -374,9 +374,10 @@ class WorkflowService(object):
# a BPMN standard, and should not be included in the display.
if task.properties and "display_name" in task.properties:
try:
task.title = spiff_task.workflow.script_engine.evaluate_expression(spiff_task, task.properties['display_name'])
task.title = spiff_task.workflow.script_engine.evaluate_expression(spiff_task, task.properties[Task.PROP_EXTENSIONS_TITLE])
except Exception as e:
app.logger.error("Failed to set title on task due to type error." + str(e), exc_info=True)
raise ApiError.from_task(code="task_title_error", message="Could not set task title on task %s with '%s' property because %s" %
(spiff_task.task_spec.name, Task.PROP_EXTENSIONS_TITLE, str(e)), task=spiff_task)
elif task.title and ' ' in task.title:
task.title = task.title.partition(' ')[2]
return task

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_389ac74" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
<decision id="Decision_CheckPI" name="Check for PI">
<extensionElements>
<biodi:bounds x="157" y="81" width="180" height="80" />
</extensionElements>
<decisionTable id="decisionTable_1">
<input id="input_1" label="Check for PI">
<inputExpression id="inputExpression_1" typeRef="string">
<text>investigators.get('PI','None Found')</text>
</inputExpression>
</input>
<output id="output_1" label="PI Found" name="is_pi" typeRef="boolean" />
<rule id="DecisionRule_0513h6e">
<inputEntry id="UnaryTests_18pzg5h">
<text>"None Found"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0voyjpp">
<text>false</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1j7k6d3">
<inputEntry id="UnaryTests_0ezhr0y">
<text></text>
</inputEntry>
<outputEntry id="LiteralExpression_05plngz">
<text>true</text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

View File

@ -0,0 +1,466 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_d28686b" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
<decision id="Decision_53dac17" name="Decision 1">
<extensionElements>
<biodi:bounds x="290" y="130" width="180" height="80" />
</extensionElements>
<decisionTable id="decisionTable_1">
<input id="input_1" label="PI Department">
<inputExpression id="inputExpression_1" typeRef="string">
<text>PI_department</text>
</inputExpression>
</input>
<output id="output_1" label="Chair Name &#38; Degree" name="Chair_Name_Degree" typeRef="string" />
<output id="OutputClause_0a23e1m" label="Chair Computer ID" name="Chair_CID" typeRef="string" />
<output id="OutputClause_0ysj4lb" label="Chair Title" name="Chair_Title" typeRef="string" />
<rule id="DecisionRule_130my8k">
<inputEntry id="UnaryTests_0utry5v">
<text>"Anesthesiology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0tk1vjc">
<text>"George F. Rich, MD, PhD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0npmzip">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0e67jw1">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1p25iet">
<inputEntry id="UnaryTests_1twyz8n">
<text>"Biochemistry &amp; Molecular Genetics"</text>
</inputEntry>
<outputEntry id="LiteralExpression_02ypl0q">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0mk1ouw">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1g170wj">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_11vnz24">
<inputEntry id="UnaryTests_1n5hdk0">
<text>"Biomedical Engineering"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1nbiz8o">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1ki2y5r">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0zidebq">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0o9l1g4">
<inputEntry id="UnaryTests_00c9fvd">
<text>"Brain Institute"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0e4jt7e">
<text>"Jaideep Kapur, MD, PhD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0a5eyr5">
<text>"jk8t"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1kjp55c">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_07agfmq">
<inputEntry id="UnaryTests_1ne2xho">
<text>"Cell Biology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0wfnk1a">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1mt2ueq">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1bdq1nk">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0tbdzg7">
<inputEntry id="UnaryTests_192cb1q">
<text>"Center for Diabetes Technology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_10za2my">
<text>"Harry G. Mitchell"</text>
</outputEntry>
<outputEntry id="LiteralExpression_00jss4e">
<text>"hgm7s"</text>
</outputEntry>
<outputEntry id="LiteralExpression_096h7xv">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0mnaifs">
<inputEntry id="UnaryTests_1pbp49w">
<text>"Center for Research in Reproduction"</text>
</inputEntry>
<outputEntry id="LiteralExpression_19cb1bz">
<text>"John C. Marshall, MD, PhD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0zkt3i2">
<text>"jcm9h"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0uktq93">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1g9heo9">
<inputEntry id="UnaryTests_06vfwmk">
<text>"Dermatology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1apthzx">
<text>"Art P. Saavedra, MD, PhD, MBA"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1yav83a">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0hhk5mn">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1w4vnv2">
<inputEntry id="UnaryTests_1uxzlwk">
<text>"Emergency Medicine"</text>
</inputEntry>
<outputEntry id="LiteralExpression_00rdpy1">
<text>"Robert O'Connor, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0y4klbl">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_00v04f6">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0v9kyu9">
<inputEntry id="UnaryTests_0obk165">
<text>"Family Medicine"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0g02cea">
<text>"Li Li, MD, PhD, MPH"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1u4cfnj">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_06vuegj">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0yft3o2">
<inputEntry id="UnaryTests_11hmf6p">
<text>"Institute of Law, Psychiatry and Public Policy (institutional)"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1en1sr3">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1k99mrq">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0q5jqja">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0tn1ntu">
<inputEntry id="UnaryTests_03sw24v">
<text>"Keck Center for Cellular Imaging (institutional)"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0rzmxbc">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_13i4uts">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1c1hbm4">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1xa7pks">
<inputEntry id="UnaryTests_1pppuin">
<text>"Kinesiology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0f8mbsy">
<text>"Arthur L. Weltman"</text>
</outputEntry>
<outputEntry id="LiteralExpression_17bh2dl">
<text>"alw2v"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1ktzrw6">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_07gq82a">
<inputEntry id="UnaryTests_1usw6cv">
<text>"Microbiology, Immunology, and Cancer Biology (MIC)"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0zas7lc">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0ayt0hb">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1t5vcgd">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1ugttjx">
<inputEntry id="UnaryTests_0l14jnz">
<text>"Molecular Physiology &amp; Biological Physics"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0nz91ut">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0cmnhcl">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1mvclh2">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_13zj816">
<inputEntry id="UnaryTests_03te6ro">
<text>"Neurology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1ym154j">
<text>"Howard Goodkin MD, PhD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0i51oau">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0txl5cj">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1d162e6">
<inputEntry id="UnaryTests_0t4sokv">
<text>"Neuroscience"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1lszybr">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1tfzksp">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1976phh">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1qa4tbk">
<inputEntry id="UnaryTests_0h7ex0k">
<text>"Neurosurgery"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1ivww3e">
<text>"Mark E. Shaffrey, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1jrc8uu">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1xdcxk9">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_194hj7g">
<inputEntry id="UnaryTests_1lmoxki">
<text>"Obstetrics &amp; Gynecology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0l5nykm">
<text>"James (Jef) E  Ferguson II, MD, MBA"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1d2368t">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0jwhpxm">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1feefxw">
<inputEntry id="UnaryTests_1bquriu">
<text>"Ophthalmology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0rcmv2x">
<text>"Peter Netland, MD, PhD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1cvve9k">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0lb9uaq">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0kk6ajr">
<inputEntry id="UnaryTests_0j98tua">
<text>"Orthopedic Surgery"</text>
</inputEntry>
<outputEntry id="LiteralExpression_14lbprk">
<text>"A. Bobby Chhabra, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1jpdhy8">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_16su4fp">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1ckz8ox">
<inputEntry id="UnaryTests_1gkxt51">
<text>"Otolaryngology- Head &amp; Neck Surgery"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1urdeg3">
<text>"Stephen S. Park, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1jxatpo">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1puli8h">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_04eribm">
<inputEntry id="UnaryTests_1a11t50">
<text>"Pathology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1ovk0xq">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0kh06ih">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0dc4w43">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_04do91b">
<inputEntry id="UnaryTests_1hg6qgn">
<text>"Pediatrics"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1h4gtcc">
<text>"James P. Nataro, MD, PhD, MBA, FAAP"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0wipbsc">
<text>"jpn2r"</text>
</outputEntry>
<outputEntry id="LiteralExpression_18uyr1o">
<text>"Chair, Department of Pediatrics"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0lb8hi5">
<inputEntry id="UnaryTests_0y76uqi">
<text>"Pharmacology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0xu1r2k">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0zjqu5t">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_12a5zfs">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0csfjb9">
<inputEntry id="UnaryTests_0ccnf2c">
<text>"Plastic and Maxillofacial Surgery"</text>
</inputEntry>
<outputEntry id="LiteralExpression_09ynoch">
<text>"Thomas J. Gampper, MD, FACS"</text>
</outputEntry>
<outputEntry id="LiteralExpression_0so2ly5">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0ized9e">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0ie3f70">
<inputEntry id="UnaryTests_10hi0vn">
<text>"Psychiatry and Neurobehavioral Sciences"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1tcqtd0">
<text>"Anita H. Clayton, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_05qrc3z">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_16paqdh">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1iavxz0">
<inputEntry id="UnaryTests_1myl3be">
<text>"Public Health Sciences"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1ayhurb">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0kdn3sp">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_193gp8u">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1d7j3pd">
<inputEntry id="UnaryTests_1m7gkcr">
<text>"Radiation Oncology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_11ufvnv">
<text>"James M. Larner, MD, FASTRO"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1xg47wl">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1bm58kb">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_0gzdz53">
<inputEntry id="UnaryTests_0mo9711">
<text>"Radiology and Medical Imaging"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1v4defw">
<text>"Alan H. Matsumoto, MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_07shsb0">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0gqqxxj">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_1immrvr">
<inputEntry id="UnaryTests_01pmp6n">
<text>"Surgery"</text>
</inputEntry>
<outputEntry id="LiteralExpression_01ao8qh">
<text>"Alexander S. Krupnick , MD"</text>
</outputEntry>
<outputEntry id="LiteralExpression_026jlgr">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_1yqde5y">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_148egsn">
<inputEntry id="UnaryTests_0x77krc">
<text>"Urology"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1qsi7o3">
<text>"Kristen L.Greene, MD, MAS, FACS"</text>
</outputEntry>
<outputEntry id="LiteralExpression_1xwdb9q">
<text></text>
</outputEntry>
<outputEntry id="LiteralExpression_0hi3yzf">
<text></text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

View File

@ -0,0 +1,216 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/1.0" id="Definitions_a3b9c9b" name="DRD" namespace="http://camunda.org/schema/1.0/dmn">
<decision id="Decision_PI_Dept" name="PI Department">
<extensionElements>
<biodi:bounds x="300" y="140" width="180" height="80" />
</extensionElements>
<decisionTable id="decisionTable_1">
<input id="InputClause_12xvnxx" label="E0 Dept">
<inputExpression id="LiteralExpression_1q9d9zi" typeRef="string">
<text>E0_dept</text>
</inputExpression>
</input>
<output id="output_1" label="PI Department" name="PI_department" typeRef="string" />
<rule id="DecisionRule_1b5ywn5">
<inputEntry id="UnaryTests_1bev7id">
<text>"ANES"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1nzq40i">
<text>"Anesthesiology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0wbq6tr">
<inputEntry id="UnaryTests_1vs880z">
<text>"BIOC"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0tgoozf">
<text>"Biochemistry &amp; Molecular Genetics"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0zojm1d">
<inputEntry id="UnaryTests_0kgwioh">
<text>"BIOM"</text>
</inputEntry>
<outputEntry id="LiteralExpression_08w2wq9">
<text>"Biomedical Engineering"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0owmu0q">
<inputEntry id="UnaryTests_0rywcw8">
<text>"CELL"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0ru3sax">
<text>"Cell Biology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1ryvd9v">
<inputEntry id="UnaryTests_0yrysju">
<text>"DMED"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1c4iwlq">
<text></text>
</outputEntry>
</rule>
<rule id="DecisionRule_11nfq9u">
<inputEntry id="UnaryTests_15017iw">
<text>"INMD"</text>
</inputEntry>
<outputEntry id="LiteralExpression_193ae27">
<text>"Institute of Law, Psychiatry and Public Policy (institutional)"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0lwmys9">
<inputEntry id="UnaryTests_0bgwlbf">
<text>"INMD-Ctr"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1p0b3ea">
<text>"Keck Center for Cellular Imaging (institutional)"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1qjzff0">
<inputEntry id="UnaryTests_10jnj9r">
<text>"MICR"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1qpt4pk">
<text>"Microbiology, Immunology, and Cancer Biology (MIC)"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_08qhcy9">
<inputEntry id="UnaryTests_19uyawr">
<text>"MPHY"</text>
</inputEntry>
<outputEntry id="LiteralExpression_06z2wux">
<text>"Molecular Physiology &amp; Biological Physics"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0ovrx5p">
<inputEntry id="UnaryTests_0pg1um2">
<text>"NERS"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0p5gvct">
<text>"Neurosurgery"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_135q0hq">
<inputEntry id="UnaryTests_0e11w4s">
<text>"NESC"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0bu5hgk">
<text>"Neuroscience"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_18zb09n">
<inputEntry id="UnaryTests_0fvagjn">
<text>"NEUR"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0tl3ksn">
<text>"Neurology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1vev1e3">
<inputEntry id="UnaryTests_07qj3jf">
<text>"OBGY"</text>
</inputEntry>
<outputEntry id="LiteralExpression_067ehpk">
<text>"Obstetrics and Gynecology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_08k4jec">
<inputEntry id="UnaryTests_0nlzxc2">
<text>"OPHT"</text>
</inputEntry>
<outputEntry id="LiteralExpression_103y6qq">
<text>"Ophthalmology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0a48i89">
<inputEntry id="UnaryTests_1y5nfzo">
<text>"ORTP"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1cr3wq0">
<text>"Orthopaedic Surgery"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0km2u3f">
<inputEntry id="UnaryTests_1buhr78">
<text>"PATH"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0nx1reo">
<text>"Pathology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1gc10ny">
<inputEntry id="UnaryTests_1uru4m4">
<text>"PBHS"</text>
</inputEntry>
<outputEntry id="LiteralExpression_073f0bn">
<text>"Public Health Sciences"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_145vhtj">
<inputEntry id="UnaryTests_1y8kr8n">
<text>"PEDT"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1k444fj">
<text>"Pediatrics"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_05u0zki">
<inputEntry id="UnaryTests_1uudg05">
<text>"PHAR"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1mz3u7d">
<text>"Pharmacology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0o9ozyh">
<inputEntry id="UnaryTests_1ytw7l4">
<text>"PLSR"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0mxv6ov">
<text>"Plastic and Maxillofacial Surgery"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0wbzqhg">
<inputEntry id="UnaryTests_0uwi3mu">
<text>"PSCH"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1lsruwb">
<text>"Psychiatry and Neurobehavioral Sciences"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1ukpgze">
<inputEntry id="UnaryTests_0ijuf1f">
<text>"RADL"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1tjwp0q">
<text>"Radiology and Medical Imaging"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_04la8a6">
<inputEntry id="UnaryTests_1f5hv2r">
<text>"RONC"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0g10afk">
<text>"Radiation Oncology"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0qwccau">
<inputEntry id="UnaryTests_0661n6g">
<text>"SURG"</text>
</inputEntry>
<outputEntry id="LiteralExpression_1iuug6l">
<text>"Surgery"</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0jleevh">
<inputEntry id="UnaryTests_1cpprhv">
<text>"UROL"</text>
</inputEntry>
<outputEntry id="LiteralExpression_0kllkvf">
<text>"Urology"</text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_06pyjz2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_06pyjz2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0">
<bpmn:process id="Process_01143nb" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_0kcrx5l</bpmn:outgoing>
@ -7,76 +7,250 @@
<bpmn:scriptTask id="ScriptTask_LoadPersonnel" name="Load IRB Personnel">
<bpmn:incoming>Flow_0kcrx5l</bpmn:incoming>
<bpmn:outgoing>Flow_1dcsioh</bpmn:outgoing>
<bpmn:script>StudyInfo = {}
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
<bpmn:script>investigators = study_info('investigators')</bpmn:script>
</bpmn:scriptTask>
<bpmn:endEvent id="EndEvent_1qor16n">
<bpmn:documentation>## The following information was gathered:
{% for type, investigator in StudyInfo.investigators.items() %}
### {{investigator.label}}: {{investigator.display_name}}
* Edit Acess? {{investigator.edit_access}}
* Send Emails? {{investigator.emails}}
{% if investigator.label == "Primary Investigator" %}
* Experience: {{investigator.experience}}
{% endif %}
{% endfor %}</bpmn:documentation>
<bpmn:incoming>Flow_1mplloa</bpmn:incoming>
{% if pi|length == 1 %}
### PI: {{ pi.PI.display_name }}
* Edit Acess? {{ pi.edit_access }}
* Send Emails? {{ pi.emails }}
* Experience: {{ pi.experience }}
{% else %}
### No PI in PB
{% endif %}</bpmn:documentation>
<bpmn:incoming>Flow_1n0k4pd</bpmn:incoming>
<bpmn:incoming>Flow_1oqem42</bpmn:incoming>
</bpmn:endEvent>
<bpmn:userTask id="Activity_EditOtherPersonnel" name="Update Personnel" camunda:formKey="Access &#38; Notifications">
<bpmn:userTask id="Activity_EditPI" name="Update PI Info" camunda:formKey="PI_AccessEmailsExperience">
<bpmn:documentation>### Please provide supplemental information for:
#### {{investigator.display_name}}
##### Title: {{investigator.title}}
#### {{ pi.PI.display_name }}
##### Title: {{ pi.PI.title }}
##### Department: {{investigator.department}}
##### Affiliation: {{investigator.affiliation}}</bpmn:documentation>
##### Department: {{ PI_department }}
##### Affiliation: {{ pi.PI.affiliation }}</bpmn:documentation>
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="investigator.edit_access" label="Should have Study Team editing access in the system?" type="boolean" defaultValue="false" />
<camunda:formField id="investigator.emails" label="Should receive automated email notifications?" type="boolean" defaultValue="false" />
<camunda:formField id="investigator.experience" label="Investigator&#39;s Experience" type="textarea">
<camunda:formField id="pi.edit_access" label="Should the Principal Investigator have full editing access in the system?" type="boolean" defaultValue="true" />
<camunda:formField id="pi.emails" label="Should the Principal Investigator receive automated email notifications?" type="boolean" defaultValue="true" />
<camunda:formField id="pi.experience" label="Investigator&#39;s Experience" type="textarea">
<camunda:properties>
<camunda:property id="rows" value="5" />
<camunda:property id="hide_expression" value="model.investigator.label !== &#34;Primary Investigator&#34;" />
</camunda:properties>
</camunda:formField>
</camunda:formData>
<camunda:properties>
<camunda:property name="display_name" value="investigator.label" />
<camunda:property name="display_name" value="pi.PI.label" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_1dcsioh</bpmn:incoming>
<bpmn:incoming>Flow_07f7kkd</bpmn:incoming>
<bpmn:outgoing>Flow_1mplloa</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics camunda:collection="StudyInfo.investigators" camunda:elementVariable="investigator" />
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0kcrx5l" sourceRef="StartEvent_1" targetRef="ScriptTask_LoadPersonnel" />
<bpmn:sequenceFlow id="Flow_1mplloa" sourceRef="Activity_EditOtherPersonnel" targetRef="EndEvent_1qor16n" />
<bpmn:sequenceFlow id="Flow_1dcsioh" sourceRef="ScriptTask_LoadPersonnel" targetRef="Activity_EditOtherPersonnel" />
<bpmn:sequenceFlow id="Flow_1mplloa" sourceRef="Activity_EditPI" targetRef="Activity_0r8pam5" />
<bpmn:sequenceFlow id="Flow_1dcsioh" sourceRef="ScriptTask_LoadPersonnel" targetRef="Activity_0bg56lv" />
<bpmn:scriptTask id="Activity_0bg56lv" name="Check for PI">
<bpmn:incoming>Flow_1dcsioh</bpmn:incoming>
<bpmn:outgoing>Flow_1vgepkq</bpmn:outgoing>
<bpmn:script>pi = {x:investigators[x] for x in investigators.keys() if x[:2] == 'PI'}</bpmn:script>
</bpmn:scriptTask>
<bpmn:exclusiveGateway id="Gateway_CheckForPI" name="PI Cnt">
<bpmn:incoming>Flow_1vgepkq</bpmn:incoming>
<bpmn:outgoing>Flow_147b9li</bpmn:outgoing>
<bpmn:outgoing>Flow_00prawo</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_147b9li" name="1 PI from PB" sourceRef="Gateway_CheckForPI" targetRef="Activity_DeterminePI_Department">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">len(pi.keys()) == 1</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_00prawo" name="No PI from PB" sourceRef="Gateway_CheckForPI" targetRef="Activity_1qwzwyi">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">len(pi.keys()) == 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:manualTask id="Activity_1qwzwyi" name="Show No PI">
<bpmn:documentation>No PI entered in PB</bpmn:documentation>
<bpmn:incoming>Flow_00prawo</bpmn:incoming>
<bpmn:outgoing>Flow_14ti38o</bpmn:outgoing>
</bpmn:manualTask>
<bpmn:sequenceFlow id="Flow_0elbjpd" sourceRef="Activity_0r8pam5" targetRef="Gateway_0jykh6r" />
<bpmn:scriptTask id="Activity_0r8pam5" name="Check for Study Coordinators">
<bpmn:incoming>Flow_1mplloa</bpmn:incoming>
<bpmn:incoming>Flow_14ti38o</bpmn:incoming>
<bpmn:outgoing>Flow_0elbjpd</bpmn:outgoing>
<bpmn:script>scs = {x:investigators[x] for x in investigators.keys() if x[:3] == 'SC_'}</bpmn:script>
</bpmn:scriptTask>
<bpmn:exclusiveGateway id="Gateway_0jykh6r">
<bpmn:incoming>Flow_0elbjpd</bpmn:incoming>
<bpmn:outgoing>Flow_0xifvai</bpmn:outgoing>
<bpmn:outgoing>Flow_1oqem42</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0xifvai" name="1 or more Study Coordinators" sourceRef="Gateway_0jykh6r" targetRef="Activity_1bcnjyq">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">len(scs.keys()) &gt;= 1</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_1n0k4pd" sourceRef="Activity_1bcnjyq" targetRef="EndEvent_1qor16n" />
<bpmn:userTask id="Activity_1bcnjyq" name="Update SC Info" camunda:formKey="SC_AccessEmails">
<bpmn:documentation>### Please provide supplemental information for:
#### {{ sc.display_name }}
##### Title: {{ sc.title }}
##### Department: {{ sc.department }}
##### Affiliation: {{ sc.affiliation }}</bpmn:documentation>
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="sc.access" label="Should this Study Coordinator have full editing access in the system?" type="boolean" defaultValue="true" />
<camunda:formField id="sc.emails" label="Should this Study Coordinator receive automated email notifications?" type="boolean" defaultValue="true" />
</camunda:formData>
<camunda:properties>
<camunda:property name="display_name" value="sc.label" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0xifvai</bpmn:incoming>
<bpmn:outgoing>Flow_1n0k4pd</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics isSequential="true" camunda:collection="scs" camunda:elementVariable="sc" />
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1oqem42" name="No Study Coordinators" sourceRef="Gateway_0jykh6r" targetRef="EndEvent_1qor16n">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">len(scs.keys()) == 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_14ti38o" sourceRef="Activity_1qwzwyi" targetRef="Activity_0r8pam5" />
<bpmn:scriptTask id="Activity_DeterminePI_Department" name="Determine PI E0 Department">
<bpmn:incoming>Flow_147b9li</bpmn:incoming>
<bpmn:outgoing>Flow_1grahhv</bpmn:outgoing>
<bpmn:script>LDAP_dept = pi.PI.department
length_LDAP_dept = len(LDAP_dept)
E0_start = LDAP_dept.find("E0:") + 3
E0_slice = LDAP_dept[E0_start:length_LDAP_dept]
E0_first_hyphen = E0_slice.find("-")
E0_dept_start = E0_first_hyphen + 1
E0_school = E0_slice[0:E0_first_hyphen]
isSpace = " " in E0_slice
E0_spec = ""
E0_dept = ""
if isSpace:
E0_first_space = E0_slice.find(" ")
E0_spec_start = E0_first_space + 1
E0_spec_end = len(E0_slice)
E0_dept = E0_slice[E0_dept_start:E0_first_space]
E0_spec = E0_slice[E0_spec_start:E0_spec_end]
</bpmn:script>
</bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_1vgepkq" sourceRef="Activity_0bg56lv" targetRef="Gateway_CheckForPI" />
<bpmn:sequenceFlow id="Flow_1grahhv" sourceRef="Activity_DeterminePI_Department" targetRef="Activity_1aeas6q" />
<bpmn:sequenceFlow id="Flow_07f7kkd" sourceRef="Activity_1aeas6q" targetRef="Activity_EditPI" />
<bpmn:businessRuleTask id="Activity_1aeas6q" name="Determine PI Department" camunda:decisionRef="Decision_PI_Dept">
<bpmn:incoming>Flow_1grahhv</bpmn:incoming>
<bpmn:outgoing>Flow_07f7kkd</bpmn:outgoing>
</bpmn:businessRuleTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_01143nb">
<bpmndi:BPMNEdge id="Flow_07f7kkd_di" bpmnElement="Flow_07f7kkd">
<di:waypoint x="990" y="120" />
<di:waypoint x="1130" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1grahhv_di" bpmnElement="Flow_1grahhv">
<di:waypoint x="830" y="120" />
<di:waypoint x="890" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1vgepkq_di" bpmnElement="Flow_1vgepkq">
<di:waypoint x="500" y="120" />
<di:waypoint x="565" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_14ti38o_di" bpmnElement="Flow_14ti38o">
<di:waypoint x="1230" y="240" />
<di:waypoint x="1340" y="240" />
<di:waypoint x="1340" y="160" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1oqem42_di" bpmnElement="Flow_1oqem42">
<di:waypoint x="1480" y="145" />
<di:waypoint x="1480" y="270" />
<di:waypoint x="1830" y="270" />
<di:waypoint x="1830" y="138" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1625" y="236" width="64" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1n0k4pd_di" bpmnElement="Flow_1n0k4pd">
<di:waypoint x="1720" y="120" />
<di:waypoint x="1812" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0xifvai_di" bpmnElement="Flow_0xifvai">
<di:waypoint x="1505" y="120" />
<di:waypoint x="1620" y="120" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1510" y="86" width="79" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0elbjpd_di" bpmnElement="Flow_0elbjpd">
<di:waypoint x="1390" y="120" />
<di:waypoint x="1455" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00prawo_di" bpmnElement="Flow_00prawo">
<di:waypoint x="590" y="145" />
<di:waypoint x="590" y="240" />
<di:waypoint x="1130" y="240" />
<bpmndi:BPMNLabel>
<dc:Bounds x="688" y="222" width="71" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_147b9li_di" bpmnElement="Flow_147b9li">
<di:waypoint x="615" y="120" />
<di:waypoint x="730" y="120" />
<bpmndi:BPMNLabel>
<dc:Bounds x="615" y="103" width="63" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1dcsioh_di" bpmnElement="Flow_1dcsioh">
<di:waypoint x="360" y="120" />
<di:waypoint x="420" y="120" />
<di:waypoint x="350" y="120" />
<di:waypoint x="400" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1mplloa_di" bpmnElement="Flow_1mplloa">
<di:waypoint x="520" y="120" />
<di:waypoint x="602" y="120" />
<di:waypoint x="1230" y="120" />
<di:waypoint x="1290" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0kcrx5l_di" bpmnElement="Flow_0kcrx5l">
<di:waypoint x="188" y="120" />
<di:waypoint x="260" y="120" />
<di:waypoint x="250" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="152" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ScriptTask_0h49cmf_di" bpmnElement="ScriptTask_LoadPersonnel">
<dc:Bounds x="260" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0d622qi_di" bpmnElement="Activity_EditOtherPersonnel">
<dc:Bounds x="420" y="80" width="100" height="80" />
<dc:Bounds x="250" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1qor16n_di" bpmnElement="EndEvent_1qor16n">
<dc:Bounds x="602" y="102" width="36" height="36" />
<dc:Bounds x="1812" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0d622qi_di" bpmnElement="Activity_EditPI">
<dc:Bounds x="1130" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1dq6tzx_di" bpmnElement="Activity_0bg56lv">
<dc:Bounds x="400" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0qzf1r3_di" bpmnElement="Gateway_CheckForPI" isMarkerVisible="true">
<dc:Bounds x="565" y="95" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="574" y="71" width="31" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0neg931_di" bpmnElement="Activity_1qwzwyi">
<dc:Bounds x="1130" y="200" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1ktvk27_di" bpmnElement="Activity_0r8pam5">
<dc:Bounds x="1290" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0jykh6r_di" bpmnElement="Gateway_0jykh6r" isMarkerVisible="true">
<dc:Bounds x="1455" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1nz85vv_di" bpmnElement="Activity_1bcnjyq">
<dc:Bounds x="1620" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1z05bvn_di" bpmnElement="Activity_DeterminePI_Department">
<dc:Bounds x="730" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0uz6yhu_di" bpmnElement="Activity_1aeas6q">
<dc:Bounds x="890" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>

View File

@ -0,0 +1,41 @@
"""empty message
Revision ID: 69081f1ff387
Revises: 1c3f88dbccc3
Create Date: 2020-08-12 09:58:36.886096
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '69081f1ff387'
down_revision = '1c3f88dbccc3'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('study_event',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('study_id', sa.Integer(), nullable=False),
sa.Column('create_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('status', sa.Enum('in_progress', 'hold', 'open_for_enrollment', 'abandoned', name='studystatusenum'), nullable=True),
sa.Column('comment', sa.String(), nullable=True),
sa.Column('event_type', sa.Enum('user', 'automatic', name='studyeventtype'), nullable=True),
sa.Column('user_uid', sa.String(), nullable=True),
sa.ForeignKeyConstraint(['study_id'], ['study.id'], ),
sa.ForeignKeyConstraint(['user_uid'], ['user.uid'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('study_event')
op.execute('drop type studystatusenum')
op.execute('drop type studyeventtype')
# ### end Alembic commands ###

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_17fwemw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.3">
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_17fwemw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.0.0">
<bpmn:process id="MultiInstance" isExecutable="true">
<bpmn:startEvent id="StartEvent_1" name="StartEvent_1">
<bpmn:outgoing>Flow_0t6p1sb</bpmn:outgoing>
@ -18,7 +18,7 @@
<camunda:formField id="email" label="Email Address:" type="string" />
</camunda:formData>
<camunda:properties>
<camunda:property name="display_name" value="{{investigator.label}}" />
<camunda:property name="display_name" value="investigator.label" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>SequenceFlow_1p568pp</bpmn:incoming>

View File

@ -11,7 +11,7 @@ from crc.models.protocol_builder import ProtocolBuilderStatus, \
ProtocolBuilderStudySchema
from crc.models.approval import ApprovalStatus
from crc.models.task_event import TaskEventModel
from crc.models.study import StudyModel, StudySchema, StudyStatus
from crc.models.study import StudyEvent, StudyModel, StudySchema, StudyStatus, StudyEventType
from crc.models.workflow import WorkflowSpecModel, WorkflowModel
from crc.services.file_service import FileService
from crc.services.workflow_processor import WorkflowProcessor
@ -134,10 +134,12 @@ class TestStudyApi(BaseTest):
def test_update_study(self):
self.load_example_data()
update_comment = 'Updating the study'
study: StudyModel = session.query(StudyModel).first()
study.title = "Pilot Study of Fjord Placement for Single Fraction Outcomes to Cortisol Susceptibility"
study_schema = StudySchema().dump(study)
study_schema['status'] = StudyStatus.in_progress.value
study_schema['comment'] = update_comment
rv = self.app.put('/v1.0/study/%i' % study.id,
content_type="application/json",
headers=self.logged_in_headers(),
@ -147,6 +149,13 @@ class TestStudyApi(BaseTest):
self.assertEqual(study.title, json_data['title'])
self.assertEqual(study.status.value, json_data['status'])
# Making sure events history is being properly recorded
study_event = session.query(StudyEvent).first()
self.assertIsNotNone(study_event)
self.assertEqual(study_event.status, StudyStatus.in_progress)
self.assertEqual(study_event.comment, update_comment)
self.assertEqual(study_event.user_uid, self.test_uid)
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_investigators') # mock_studies
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_required_docs') # mock_docs
@patch('crc.services.protocol_builder.ProtocolBuilderService.get_study_details') # mock_details
@ -245,8 +254,15 @@ class TestStudyApi(BaseTest):
def test_delete_study_with_workflow_and_status(self):
self.load_example_data()
workflow = session.query(WorkflowModel).first()
stats1 = StudyEvent(
study_id=workflow.study_id,
status=StudyStatus.in_progress,
comment='Some study status change event',
event_type=StudyEventType.user,
user_uid=self.users[0]['uid'],
)
stats2 = TaskEventModel(study_id=workflow.study_id, workflow_id=workflow.id, user_uid=self.users[0]['uid'])
session.add(stats2)
session.add_all([stats1, stats2])
session.commit()
rv = self.app.delete('/v1.0/study/%i' % workflow.study_id, headers=self.logged_in_headers())
self.assert_success(rv)

View File

@ -19,7 +19,7 @@ class TestStudyDetailsDocumentsScript(BaseTest):
"""
1. get a list of all documents related to the study.
2. For this study, is this document required accroding to the protocol builder?
2. For this study, is this document required accroding to the protocol builder?
3. For ALL uploaded documents, what the total number of files that were uploaded? per instance of this document naming
convention that we are implementing for the IRB.
"""

View File

@ -84,7 +84,7 @@ class TestStudyService(BaseTest):
# Assure the workflow is now started, and knows the total and completed tasks.
studies = StudyService.get_studies_for_user(user)
workflow = next(iter(studies[0].categories[0].workflows)) # Workflows is a set.
# self.assertEqual(WorkflowStatus.user_input_required, workflow.status)
# self.assertEqual(WorkflowStatus.user_input_required, workflow.status)
self.assertTrue(workflow.total_tasks > 0)
self.assertEqual(0, workflow.completed_tasks)
self.assertIsNotNone(workflow.spec_version)

View File

@ -273,7 +273,7 @@ class TestTasksApi(BaseTest):
self.assertEqual(5, workflow.next_task.multi_instance_count)
# Assure that the names for each task are properly updated, so they aren't all the same.
self.assertEqual("Primary Investigator", workflow.next_task.properties['display_name'])
self.assertEqual("Primary Investigator", workflow.next_task.title)
def test_lookup_endpoint_for_task_field_enumerations(self):
workflow = self.create_workflow('enum_options_with_search')