Merge pull request #91 from sartography/feature/approvals_enhancements

Approvals enhancements
This commit is contained in:
Aaron Louie 2020-06-01 00:46:59 -04:00 committed by GitHub
commit bb32bd7090
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 504 additions and 268 deletions

View File

@ -173,6 +173,30 @@ paths:
application/json: application/json:
schema: schema:
$ref: "#/components/schemas/Study" $ref: "#/components/schemas/Study"
/study/{study_id}/approvals:
parameters:
- name: study_id
in: path
required: true
description: The id of the study for which workflows should be returned.
schema:
type: integer
format: int32
get:
operationId: crc.api.approval.get_approvals_for_study
summary: Returns approvals for a single study
tags:
- Studies
- Approvals
responses:
'200':
description: An array of approvals
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Approval"
/workflow-specification: /workflow-specification:
get: get:
operationId: crc.api.workflow.all_specifications operationId: crc.api.workflow.all_specifications

View File

@ -5,15 +5,24 @@ from crc.models.approval import Approval, ApprovalModel, ApprovalSchema
from crc.services.approval_service import ApprovalService from crc.services.approval_service import ApprovalService
def get_approvals(approver_uid = None): def get_approvals(approver_uid=None):
if not approver_uid: if not approver_uid:
db_approvals = ApprovalService.get_all_approvals() db_approvals = ApprovalService.get_all_approvals()
else: else:
db_approvals = ApprovalService.get_approvals_per_user(approver_uid) db_approvals = ApprovalService.get_approvals_per_user(approver_uid)
approvals = [Approval.from_model(approval_model) for approval_model in db_approvals] approvals = [Approval.from_model(approval_model) for approval_model in db_approvals]
results = ApprovalSchema(many=True).dump(approvals) results = ApprovalSchema(many=True).dump(approvals)
return results return results
def get_approvals_for_study(study_id=None):
db_approvals = ApprovalService.get_approvals_for_study(study_id)
approvals = [Approval.from_model(approval_model) for approval_model in db_approvals]
results = ApprovalSchema(many=True).dump(approvals)
return results
def update_approval(approval_id, body): def update_approval(approval_id, body):
if approval_id is None: if approval_id is None:
raise ApiError('unknown_approval', 'Please provide a valid Approval ID.') raise ApiError('unknown_approval', 'Please provide a valid Approval ID.')

View File

@ -12,8 +12,9 @@ from crc.services.file_service import FileService
def to_file_api(file_model): def to_file_api(file_model):
"""Converts a FileModel object to something we can return via the aip""" """Converts a FileModel object to something we can return via the api"""
return File.from_models(file_model, FileService.get_file_data(file_model.id)) return File.from_models(file_model, FileService.get_file_data(file_model.id),
FileService.get_doc_dictionary())
def get_files(workflow_spec_id=None, workflow_id=None, form_field_key=None): def get_files(workflow_spec_id=None, workflow_id=None, form_field_key=None):

View File

@ -48,12 +48,10 @@ def update_study(study_id, body):
def get_study(study_id): def get_study(study_id):
study_service = StudyService() study = StudyService.get_study(study_id)
study = study_service.get_study(study_id)
if (study is None): if (study is None):
raise ApiError("Study not found", status_code=404) raise ApiError("Study not found", status_code=404)
schema = StudySchema() return StudySchema().dump(study)
return schema.dump(study)
def delete_study(study_id): def delete_study(study_id):

View File

@ -119,6 +119,8 @@ def __get_workflow_api_model(processor: WorkflowProcessor, next_task = None):
navigation.append(NavigationItem(**nav_item)) navigation.append(NavigationItem(**nav_item))
NavigationItemSchema().dump(nav_item) NavigationItemSchema().dump(nav_item)
spec = session.query(WorkflowSpecModel).filter_by(id=processor.workflow_spec_id).first()
workflow_api = WorkflowApi( workflow_api = WorkflowApi(
id=processor.get_workflow_id(), id=processor.get_workflow_id(),
status=processor.get_status(), status=processor.get_status(),
@ -129,7 +131,8 @@ def __get_workflow_api_model(processor: WorkflowProcessor, next_task = None):
is_latest_spec=processor.is_latest_spec, is_latest_spec=processor.is_latest_spec,
total_tasks=processor.workflow_model.total_tasks, total_tasks=processor.workflow_model.total_tasks,
completed_tasks=processor.workflow_model.completed_tasks, completed_tasks=processor.workflow_model.completed_tasks,
last_updated=processor.workflow_model.last_updated last_updated=processor.workflow_model.last_updated,
title=spec.display_name
) )
if not next_task: # The Next Task can be requested to be a certain task, useful for parallel tasks. if not next_task: # The Next Task can be requested to be a certain task, useful for parallel tasks.
# This may or may not work, sometimes there is no next task to complete. # This may or may not work, sometimes there is no next task to complete.
@ -235,4 +238,4 @@ def lookup(workflow_id, field_id, query, limit):
""" """
workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first() workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first()
lookup_data = LookupService.lookup(workflow, field_id, query, limit) lookup_data = LookupService.lookup(workflow, field_id, query, limit)
return LookupDataSchema(many=True).dump(lookup_data) return LookupDataSchema(many=True).dump(lookup_data)

View File

@ -119,7 +119,7 @@ class NavigationItemSchema(ma.Schema):
class WorkflowApi(object): class WorkflowApi(object):
def __init__(self, id, status, next_task, navigation, def __init__(self, id, status, next_task, navigation,
spec_version, is_latest_spec, workflow_spec_id, total_tasks, completed_tasks, last_updated): spec_version, is_latest_spec, workflow_spec_id, total_tasks, completed_tasks, last_updated, title):
self.id = id self.id = id
self.status = status self.status = status
self.next_task = next_task # The next task that requires user input. self.next_task = next_task # The next task that requires user input.
@ -130,13 +130,14 @@ class WorkflowApi(object):
self.total_tasks = total_tasks self.total_tasks = total_tasks
self.completed_tasks = completed_tasks self.completed_tasks = completed_tasks
self.last_updated = last_updated self.last_updated = last_updated
self.title = title
class WorkflowApiSchema(ma.Schema): class WorkflowApiSchema(ma.Schema):
class Meta: class Meta:
model = WorkflowApi model = WorkflowApi
fields = ["id", "status", "next_task", "navigation", fields = ["id", "status", "next_task", "navigation",
"workflow_spec_id", "spec_version", "is_latest_spec", "total_tasks", "completed_tasks", "workflow_spec_id", "spec_version", "is_latest_spec", "total_tasks", "completed_tasks",
"last_updated"] "last_updated", "title"]
unknown = INCLUDE unknown = INCLUDE
status = EnumField(WorkflowStatus) status = EnumField(WorkflowStatus)
@ -147,7 +148,7 @@ class WorkflowApiSchema(ma.Schema):
def make_workflow(self, data, **kwargs): def make_workflow(self, data, **kwargs):
keys = ['id', 'status', 'next_task', 'navigation', keys = ['id', 'status', 'next_task', 'navigation',
'workflow_spec_id', 'spec_version', 'is_latest_spec', "total_tasks", "completed_tasks", 'workflow_spec_id', 'spec_version', 'is_latest_spec', "total_tasks", "completed_tasks",
"last_updated"] "last_updated", "title"]
filtered_fields = {key: data[key] for key in keys} filtered_fields = {key: data[key] for key in keys}
filtered_fields['next_task'] = TaskSchema().make_task(data['next_task']) filtered_fields['next_task'] = TaskSchema().make_task(data['next_task'])
return WorkflowApi(**filtered_fields) return WorkflowApi(**filtered_fields)

View File

@ -11,10 +11,11 @@ from crc.models.file import FileDataModel
from crc.models.study import StudyModel from crc.models.study import StudyModel
from crc.models.workflow import WorkflowModel from crc.models.workflow import WorkflowModel
from crc.services.ldap_service import LdapService from crc.services.ldap_service import LdapService
from crc.services.file_service import FileService
class ApprovalStatus(enum.Enum): class ApprovalStatus(enum.Enum):
WAITING = "WAITING" # no one has done jack. PENDING = "PENDING" # no one has done jack.
APPROVED = "APPROVED" # approved by the reviewer APPROVED = "APPROVED" # approved by the reviewer
DECLINED = "DECLINED" # rejected by the reviewer DECLINED = "DECLINED" # rejected by the reviewer
CANCELED = "CANCELED" # The document was replaced with a new version and this review is no longer needed. CANCELED = "CANCELED" # The document was replaced with a new version and this review is no longer needed.
@ -67,10 +68,10 @@ class Approval(object):
if model.study: if model.study:
instance.title = model.study.title instance.title = model.study.title
principal_investigator_id = model.study.primary_investigator_id
instance.approver = {} instance.approver = {}
try: try:
ldap_service = LdapService() ldap_service = LdapService()
principal_investigator_id = model.study.primary_investigator_id
user_info = ldap_service.user_info(principal_investigator_id) user_info = ldap_service.user_info(principal_investigator_id)
except (ApiError, LDAPSocketOpenError) as exception: except (ApiError, LDAPSocketOpenError) as exception:
user_info = None user_info = None
@ -84,11 +85,25 @@ class Approval(object):
instance.approver['title'] = user_info.title instance.approver['title'] = user_info.title
instance.approver['department'] = user_info.department instance.approver['department'] = user_info.department
# TODO: Organize it properly, move it to services
doc_dictionary = FileService.get_reference_data(FileService.DOCUMENT_LIST, 'code', ['id'])
instance.associated_files = [] instance.associated_files = []
for approval_file in model.approval_files: for approval_file in model.approval_files:
try:
extra_info = doc_dictionary[approval_file.file_data.file_model.irb_doc_code]
except:
extra_info = None
associated_file = {} associated_file = {}
associated_file['id'] = approval_file.file_data.file_model.id associated_file['id'] = approval_file.file_data.file_model.id
associated_file['name'] = approval_file.file_data.file_model.name if extra_info:
irb_doc_code = approval_file.file_data.file_model.irb_doc_code
associated_file['name'] = '_'.join((irb_doc_code, approval_file.file_data.file_model.name))
associated_file['description'] = extra_info['description']
else:
associated_file['name'] = approval_file.file_data.file_model.name
associated_file['description'] = 'No description available'
associated_file['name'] = '(' + principal_investigator_id + ')' + associated_file['name']
associated_file['content_type'] = approval_file.file_data.file_model.content_type associated_file['content_type'] = approval_file.file_data.file_model.content_type
instance.associated_files.append(associated_file) instance.associated_files.append(associated_file)

View File

@ -86,7 +86,7 @@ class FileModel(db.Model):
class File(object): class File(object):
@classmethod @classmethod
def from_models(cls, model: FileModel, data_model: FileDataModel): def from_models(cls, model: FileModel, data_model: FileDataModel, doc_dictionary):
instance = cls() instance = cls()
instance.id = model.id instance.id = model.id
instance.name = model.name instance.name = model.name
@ -99,6 +99,15 @@ class File(object):
instance.workflow_id = model.workflow_id instance.workflow_id = model.workflow_id
instance.irb_doc_code = model.irb_doc_code instance.irb_doc_code = model.irb_doc_code
instance.type = model.type instance.type = model.type
if model.irb_doc_code and model.irb_doc_code in doc_dictionary:
instance.category = "/".join(filter(None, [doc_dictionary[model.irb_doc_code]['category1'],
doc_dictionary[model.irb_doc_code]['category2'],
doc_dictionary[model.irb_doc_code]['category3']]))
instance.description = doc_dictionary[model.irb_doc_code]['description']
instance.download_name = ".".join([instance.category, model.type.value])
else:
instance.category = ""
instance.description = ""
if data_model: if data_model:
instance.last_modified = data_model.date_created instance.last_modified = data_model.date_created
instance.latest_version = data_model.version instance.latest_version = data_model.version
@ -122,7 +131,8 @@ class FileSchema(ma.Schema):
model = File model = File
fields = ["id", "name", "is_status", "is_reference", "content_type", fields = ["id", "name", "is_status", "is_reference", "content_type",
"primary", "primary_process_id", "workflow_spec_id", "workflow_id", "primary", "primary_process_id", "workflow_spec_id", "workflow_id",
"irb_doc_code", "last_modified", "latest_version", "type"] "irb_doc_code", "last_modified", "latest_version", "type", "categories",
"description", "category", "description", "download_name"]
unknown = INCLUDE unknown = INCLUDE
type = EnumField(FileType) type = EnumField(FileType)

View File

@ -5,7 +5,7 @@ from sqlalchemy import func
from crc import db, ma from crc import db, ma
from crc.api.common import ApiErrorSchema from crc.api.common import ApiErrorSchema
from crc.models.file import FileModel, SimpleFileSchema from crc.models.file import FileModel, SimpleFileSchema, FileSchema
from crc.models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudy from crc.models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudy
from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowState, WorkflowStatus, WorkflowSpecModel, \ from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowState, WorkflowStatus, WorkflowSpecModel, \
WorkflowModel WorkflowModel
@ -106,7 +106,8 @@ class Study(object):
def __init__(self, title, last_updated, primary_investigator_id, user_uid, def __init__(self, title, last_updated, primary_investigator_id, user_uid,
id=None, id=None,
protocol_builder_status=None, protocol_builder_status=None,
sponsor="", hsr_number="", ind_number="", categories=[], **argsv): sponsor="", hsr_number="", ind_number="", categories=[],
files=[], approvals=[], **argsv):
self.id = id self.id = id
self.user_uid = user_uid self.user_uid = user_uid
self.title = title self.title = title
@ -117,8 +118,9 @@ class Study(object):
self.hsr_number = hsr_number self.hsr_number = hsr_number
self.ind_number = ind_number self.ind_number = ind_number
self.categories = categories self.categories = categories
self.approvals = approvals
self.warnings = [] self.warnings = []
self.files = [] self.files = files
@classmethod @classmethod
def from_model(cls, study_model: StudyModel): def from_model(cls, study_model: StudyModel):
@ -149,12 +151,13 @@ class StudySchema(ma.Schema):
hsr_number = fields.String(allow_none=True) hsr_number = fields.String(allow_none=True)
sponsor = fields.String(allow_none=True) sponsor = fields.String(allow_none=True)
ind_number = fields.String(allow_none=True) ind_number = fields.String(allow_none=True)
files = fields.List(fields.Nested(SimpleFileSchema), dump_only=True) files = fields.List(fields.Nested(FileSchema), dump_only=True)
approvals = fields.List(fields.Nested('ApprovalSchema'), dump_only=True)
class Meta: class Meta:
model = Study model = Study
additional = ["id", "title", "last_updated", "primary_investigator_id", "user_uid", additional = ["id", "title", "last_updated", "primary_investigator_id", "user_uid",
"sponsor", "ind_number"] "sponsor", "ind_number", "approvals", "files"]
unknown = INCLUDE unknown = INCLUDE
@marshmallow.post_load @marshmallow.post_load

View File

@ -19,6 +19,12 @@ class ApprovalService(object):
db_approvals = session.query(ApprovalModel).filter_by(approver_uid=approver_uid).all() db_approvals = session.query(ApprovalModel).filter_by(approver_uid=approver_uid).all()
return db_approvals return db_approvals
@staticmethod
def get_approvals_for_study(study_id):
"""Returns a list of all approvals for the given study"""
db_approvals = session.query(ApprovalModel).filter_by(study_id=study_id).all()
return db_approvals
@staticmethod @staticmethod
def get_all_approvals(): def get_all_approvals():
"""Returns a list of all approvlas""" """Returns a list of all approvlas"""
@ -78,7 +84,7 @@ class ApprovalService(object):
version = 1 version = 1
model = ApprovalModel(study_id=study_id, workflow_id=workflow_id, model = ApprovalModel(study_id=study_id, workflow_id=workflow_id,
approver_uid=approver_uid, status=ApprovalStatus.WAITING.value, approver_uid=approver_uid, status=ApprovalStatus.PENDING.value,
message="", date_created=datetime.now(), message="", date_created=datetime.now(),
version=version) version=version)
approval_files = ApprovalService._create_approval_files(workflow_data_files, model) approval_files = ApprovalService._create_approval_files(workflow_data_files, model)

View File

@ -22,6 +22,14 @@ class FileService(object):
DOCUMENT_LIST = "irb_documents.xlsx" DOCUMENT_LIST = "irb_documents.xlsx"
INVESTIGATOR_LIST = "investigators.xlsx" INVESTIGATOR_LIST = "investigators.xlsx"
__doc_dictionary = None
@staticmethod
def get_doc_dictionary():
if not FileService.__doc_dictionary:
FileService.__doc_dictionary = FileService.get_reference_data(FileService.DOCUMENT_LIST, 'code', ['id'])
return FileService.__doc_dictionary
@staticmethod @staticmethod
def add_workflow_spec_file(workflow_spec: WorkflowSpecModel, def add_workflow_spec_file(workflow_spec: WorkflowSpecModel,
name, content_type, binary_data, primary=False, is_status=False): name, content_type, binary_data, primary=False, is_status=False):

View File

@ -9,7 +9,7 @@ from ldap3.core.exceptions import LDAPSocketOpenError
from crc import db, session, app from crc import db, session, app
from crc.api.common import ApiError from crc.api.common import ApiError
from crc.models.file import FileModel, FileModelSchema from crc.models.file import FileModel, FileModelSchema, File
from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus from crc.models.protocol_builder import ProtocolBuilderStudy, ProtocolBuilderStatus
from crc.models.stats import TaskEventModel from crc.models.stats import TaskEventModel
from crc.models.study import StudyModel, Study, Category, WorkflowMetadata from crc.models.study import StudyModel, Study, Category, WorkflowMetadata
@ -19,6 +19,8 @@ from crc.services.file_service import FileService
from crc.services.ldap_service import LdapService from crc.services.ldap_service import LdapService
from crc.services.protocol_builder import ProtocolBuilderService from crc.services.protocol_builder import ProtocolBuilderService
from crc.services.workflow_processor import WorkflowProcessor from crc.services.workflow_processor import WorkflowProcessor
from crc.services.approval_service import ApprovalService
from crc.models.approval import Approval
class StudyService(object): class StudyService(object):
@ -54,7 +56,13 @@ class StudyService(object):
study = Study.from_model(study_model) study = Study.from_model(study_model)
study.categories = StudyService.get_categories() study.categories = StudyService.get_categories()
workflow_metas = StudyService.__get_workflow_metas(study_id) workflow_metas = StudyService.__get_workflow_metas(study_id)
study.files = FileService.get_files_for_study(study.id) approvals = ApprovalService.get_approvals_for_study(study.id)
study.approvals = [Approval.from_model(approval_model) for approval_model in approvals]
files = FileService.get_files_for_study(study.id)
files = (File.from_models(model, FileService.get_file_data(model.id),
FileService.get_doc_dictionary()) for model in files)
study.files = list(files)
# Calling this line repeatedly is very very slow. It creates the # Calling this line repeatedly is very very slow. It creates the
# master spec and runs it. # master spec and runs it.

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" id="Definitions_06veek1" name="DRD" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<decision id="Decision_ExclusiveAMCheck" name="Exclusive AM Check">
<decisionTable id="decisionTable_1">
<input id="InputClause_1z0jy2o" label="How Many Exclusive Spaces?">
<inputExpression id="LiteralExpression_0tvij2j" typeRef="integer" expressionLanguage="python">
<text>'exclusive' in locals() and len(exclusive)</text>
</inputExpression>
</input>
<input id="input_1" label="Number Without Area Monitor">
<inputExpression id="inputExpression_1" typeRef="integer" expressionLanguage="python">
<text>sum([1 for x in exclusive if x.get('ExclusiveSpaceAMComputingID',None) == None])</text>
</inputExpression>
</input>
<output id="output_1" label="All Possible Area Monitors Entered" name="isAllExclusiveAreaMonitors" typeRef="boolean" />
<rule id="DecisionRule_07162mr">
<description>No exclusive spaces without Area Monitor</description>
<inputEntry id="UnaryTests_1892rx8">
<text>&gt;0</text>
</inputEntry>
<inputEntry id="UnaryTests_1jqxc3u">
<text>0</text>
</inputEntry>
<outputEntry id="LiteralExpression_16l50ps">
<text>true</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0ifa4wu">
<description>One or more exclusive space without an Area Monitor</description>
<inputEntry id="UnaryTests_1jakyab">
<text>&gt;0</text>
</inputEntry>
<inputEntry id="UnaryTests_0szbwxc">
<text>&gt; 0</text>
</inputEntry>
<outputEntry id="LiteralExpression_0td8sa6">
<text>false</text>
</outputEntry>
</rule>
<rule id="DecisionRule_026r0im">
<description>No exclusive spaces entered</description>
<inputEntry id="UnaryTests_0c670b6">
<text>0</text>
</inputEntry>
<inputEntry id="UnaryTests_0j06ysc">
<text></text>
</inputEntry>
<outputEntry id="LiteralExpression_1apwzvv">
<text>true</text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?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_1oogn9j" 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: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_1oogn9j" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0">
<bpmn:process id="Process_0ssahs9" isExecutable="true"> <bpmn:process id="Process_0ssahs9" isExecutable="true">
<bpmn:startEvent id="StartEvent_1"> <bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>SequenceFlow_05ja25w</bpmn:outgoing> <bpmn:outgoing>SequenceFlow_05ja25w</bpmn:outgoing>
@ -159,7 +159,7 @@ Enter the following information for the PI submitting this request</bpmn:documen
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="SequenceFlow_0h50bp3" sourceRef="ManualTask_Instructions" targetRef="Activity-PI_Info" /> <bpmn:sequenceFlow id="SequenceFlow_0h50bp3" sourceRef="ManualTask_Instructions" targetRef="Activity-PI_Info" />
<bpmn:sequenceFlow id="SequenceFlow_05ja25w" sourceRef="StartEvent_1" targetRef="ManualTask_Instructions" /> <bpmn:sequenceFlow id="SequenceFlow_05ja25w" sourceRef="StartEvent_1" targetRef="ManualTask_Instructions" />
<bpmn:userTask id="Personnel" name="Enter Personnel" camunda:formKey="Personnel"> <bpmn:userTask id="Activity_Personnel" name="Enter Personnel" camunda:formKey="Research Personnel">
<bpmn:documentation>#### Personnel for whom you are requesting access <bpmn:documentation>#### Personnel for whom you are requesting access
Provide information on all personnel you are requesting approval for reentry into the previously entered lab, workspace and/or office space(s) for conducting research on-Grounds. (If there are personnel already working in the space, include them). Provide information on all personnel you are requesting approval for reentry into the previously entered lab, workspace and/or office space(s) for conducting research on-Grounds. (If there are personnel already working in the space, include them).
@ -226,8 +226,8 @@ Provide information on all personnel you are requesting approval for reentry int
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_1eiud85</bpmn:incoming> <bpmn:incoming>Flow_0hc1r8a</bpmn:incoming>
<bpmn:outgoing>Flow_1nbjr72</bpmn:outgoing> <bpmn:outgoing>Flow_1yxaewj</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:userTask id="UserTask_CoreResource" name="Enter Core Resources" camunda:formKey="Core Resources"> <bpmn:userTask id="UserTask_CoreResource" name="Enter Core Resources" camunda:formKey="Core Resources">
<bpmn:documentation>If applicable, provide a list of any [Core Resources](https://research.virginia.edu/research-core-resources) utilization of space and/or instruments along with the name(s) and email(s) of contact person(s) in the core with whom you have coordinated your plan. (Core facility managers are responsible for developing a plan for their space)</bpmn:documentation> <bpmn:documentation>If applicable, provide a list of any [Core Resources](https://research.virginia.edu/research-core-resources) utilization of space and/or instruments along with the name(s) and email(s) of contact person(s) in the core with whom you have coordinated your plan. (Core facility managers are responsible for developing a plan for their space)</bpmn:documentation>
@ -249,8 +249,8 @@ Provide information on all personnel you are requesting approval for reentry int
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_15zy1q7</bpmn:incoming> <bpmn:incoming>Flow_1n69wsr</bpmn:incoming>
<bpmn:outgoing>Flow_12ie6w0</bpmn:outgoing> <bpmn:outgoing>Flow_13pusfu</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:endEvent id="EndEvent_09wp7av"> <bpmn:endEvent id="EndEvent_09wp7av">
<bpmn:documentation>#### End of Research Ramp-up Plan Workflow <bpmn:documentation>#### End of Research Ramp-up Plan Workflow
@ -288,6 +288,9 @@ When your Research Ramp-up Plan is complete and ready to submit for review and a
<camunda:property id="description" value="Enter the room number or other unique identifier" /> <camunda:property id="description" value="Enter the room number or other unique identifier" />
<camunda:property id="hide_expression" value="model.SharedSpaceBuilding === &#34;Other&#34;" /> <camunda:property id="hide_expression" value="model.SharedSpaceBuilding === &#34;Other&#34;" />
</camunda:properties> </camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
</camunda:formField> </camunda:formField>
<camunda:formField id="ShareSpaceRoomIDBuilding" label="Room No, and Building Name" type="string"> <camunda:formField id="ShareSpaceRoomIDBuilding" label="Room No, and Building Name" type="string">
<camunda:properties> <camunda:properties>
@ -342,28 +345,10 @@ When your Research Ramp-up Plan is complete and ready to submit for review and a
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_19xeq76</bpmn:incoming> <bpmn:incoming>Flow_0o4tg9g</bpmn:incoming>
<bpmn:outgoing>Flow_16342pm</bpmn:outgoing> <bpmn:outgoing>Flow_1n69wsr</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:parallelGateway id="Gateway_0frfdnc">
<bpmn:incoming>Flow_1v7r1tg</bpmn:incoming>
<bpmn:outgoing>Flow_19xeq76</bpmn:outgoing>
<bpmn:outgoing>Flow_0qf2y84</bpmn:outgoing>
<bpmn:outgoing>Flow_15zy1q7</bpmn:outgoing>
<bpmn:outgoing>Flow_0ya8hw8</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:parallelGateway id="Gateway_1vj4zd3">
<bpmn:incoming>Flow_0tk64b6</bpmn:incoming>
<bpmn:incoming>Flow_12ie6w0</bpmn:incoming>
<bpmn:incoming>Flow_0zz2hbq</bpmn:incoming>
<bpmn:incoming>Flow_16342pm</bpmn:incoming>
<bpmn:outgoing>Flow_1eiud85</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:sequenceFlow id="Flow_19xeq76" sourceRef="Gateway_0frfdnc" targetRef="Activity_SharedSpaceInfo" />
<bpmn:sequenceFlow id="Flow_16342pm" sourceRef="Activity_SharedSpaceInfo" targetRef="Gateway_1vj4zd3" />
<bpmn:sequenceFlow id="Flow_16y8glw" sourceRef="Activity-PI_Info" targetRef="Activity_1u58hox" /> <bpmn:sequenceFlow id="Flow_16y8glw" sourceRef="Activity-PI_Info" targetRef="Activity_1u58hox" />
<bpmn:sequenceFlow id="Flow_0qf2y84" sourceRef="Gateway_0frfdnc" targetRef="Activity_ExclusiveSpace" />
<bpmn:sequenceFlow id="Flow_0tk64b6" sourceRef="Activity_ExclusiveSpace" targetRef="Gateway_1vj4zd3" />
<bpmn:userTask id="Activity_ExclusiveSpace" name="Enter Exclusive Space" camunda:formKey="ExclusiveSpace"> <bpmn:userTask id="Activity_ExclusiveSpace" name="Enter Exclusive Space" camunda:formKey="ExclusiveSpace">
<bpmn:documentation>#### Space managed exclusively by {{ PIComputingID.label }} <bpmn:documentation>#### Space managed exclusively by {{ PIComputingID.label }}
@ -389,6 +374,9 @@ Submit one entry for each space the PI is the exclusive investigator. If all sp
<camunda:property id="repeat" value="Exclusive" /> <camunda:property id="repeat" value="Exclusive" />
<camunda:property id="description" value="Enter the room number or other unique identifier" /> <camunda:property id="description" value="Enter the room number or other unique identifier" />
</camunda:properties> </camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
</camunda:formField> </camunda:formField>
<camunda:formField id="ExclusiveSpaceRoomIDBuilding" label="Room No, and Building Name" type="string"> <camunda:formField id="ExclusiveSpaceRoomIDBuilding" label="Room No, and Building Name" type="string">
<camunda:properties> <camunda:properties>
@ -448,12 +436,9 @@ Submit one entry for each space the PI is the exclusive investigator. If all sp
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_0qf2y84</bpmn:incoming> <bpmn:incoming>Flow_0uc4o6c</bpmn:incoming>
<bpmn:outgoing>Flow_0tk64b6</bpmn:outgoing> <bpmn:outgoing>Flow_0o4tg9g</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_15zy1q7" sourceRef="Gateway_0frfdnc" targetRef="UserTask_CoreResource" />
<bpmn:sequenceFlow id="Flow_12ie6w0" sourceRef="UserTask_CoreResource" targetRef="Gateway_1vj4zd3" />
<bpmn:sequenceFlow id="Flow_0ya8hw8" sourceRef="Gateway_0frfdnc" targetRef="Activity_nonUVASpaces" />
<bpmn:userTask id="Activity_nonUVASpaces" name="Enter non-UVA Spaces" camunda:formKey="nonUVA Spaces"> <bpmn:userTask id="Activity_nonUVASpaces" name="Enter non-UVA Spaces" camunda:formKey="nonUVA Spaces">
<bpmn:extensionElements> <bpmn:extensionElements>
<camunda:formData> <camunda:formData>
@ -476,12 +461,9 @@ Submit one entry for each space the PI is the exclusive investigator. If all sp
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_0ya8hw8</bpmn:incoming> <bpmn:incoming>Flow_13pusfu</bpmn:incoming>
<bpmn:outgoing>Flow_0zz2hbq</bpmn:outgoing> <bpmn:outgoing>Flow_0hc1r8a</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0zz2hbq" sourceRef="Activity_nonUVASpaces" targetRef="Gateway_1vj4zd3" />
<bpmn:sequenceFlow id="Flow_1eiud85" sourceRef="Gateway_1vj4zd3" targetRef="Personnel" />
<bpmn:sequenceFlow id="Flow_1nbjr72" sourceRef="Personnel" targetRef="PersonnelWeeklyScheduleTask" />
<bpmn:userTask id="Activity_DistanceReq" name="Enter Distancing Requirements" camunda:formKey="Distancing Requirements"> <bpmn:userTask id="Activity_DistanceReq" name="Enter Distancing Requirements" camunda:formKey="Distancing Requirements">
<bpmn:documentation>#### Distancing requirements: <bpmn:documentation>#### Distancing requirements:
Maintain social distancing by designing space between people to be at least 9 feet during prolonged work which will be accomplished by restricting the number of people in the lab to a density of ~250 sq. ft. /person in lab areas. When moving around, a minimum of 6 feet social distancing is required. Ideally only one person per lab bench and not more than one person can work at the same time in the same bay.</bpmn:documentation> Maintain social distancing by designing space between people to be at least 9 feet during prolonged work which will be accomplished by restricting the number of people in the lab to a density of ~250 sq. ft. /person in lab areas. When moving around, a minimum of 6 feet social distancing is required. Ideally only one person per lab bench and not more than one person can work at the same time in the same bay.</bpmn:documentation>
@ -499,18 +481,9 @@ Maintain social distancing by designing space between people to be at least 9 fe
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_0p2r1bo</bpmn:incoming> <bpmn:incoming>Flow_1itd8db</bpmn:incoming>
<bpmn:outgoing>Flow_0tz5c2v</bpmn:outgoing> <bpmn:outgoing>Flow_1lo964l</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0p2r1bo" sourceRef="Gateway_18jn18b" targetRef="Activity_DistanceReq" />
<bpmn:parallelGateway id="Gateway_18jn18b">
<bpmn:incoming>Flow_097fpi3</bpmn:incoming>
<bpmn:outgoing>Flow_0p2r1bo</bpmn:outgoing>
<bpmn:outgoing>Flow_0mkh1wn</bpmn:outgoing>
<bpmn:outgoing>Flow_1yqkpgu</bpmn:outgoing>
<bpmn:outgoing>Flow_1c6m5wv</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:sequenceFlow id="Flow_0mkh1wn" sourceRef="Gateway_18jn18b" targetRef="Activity_PWA" />
<bpmn:userTask id="Activity_PWA" name="Enter Physical Work Arrangements" camunda:formKey="Physical Work Arrangements"> <bpmn:userTask id="Activity_PWA" name="Enter Physical Work Arrangements" camunda:formKey="Physical Work Arrangements">
<bpmn:documentation>Describe physical work arrangements for each lab, workspace and/or office space previously entered. Show schematic of the space organization to meet the distancing guidelines (see key safety expectations for ramp-up). <bpmn:documentation>Describe physical work arrangements for each lab, workspace and/or office space previously entered. Show schematic of the space organization to meet the distancing guidelines (see key safety expectations for ramp-up).
- Show gross dimensions, location of desks, and equipment in blocks (not details) that show available space for work and foot traffic. - Show gross dimensions, location of desks, and equipment in blocks (not details) that show available space for work and foot traffic.
@ -533,10 +506,9 @@ Maintain social distancing by designing space between people to be at least 9 fe
<camunda:formField id="PWAFiles" label="Upload supporting files" type="files" /> <camunda:formField id="PWAFiles" label="Upload supporting files" type="files" />
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_0mkh1wn</bpmn:incoming> <bpmn:incoming>Flow_1lo964l</bpmn:incoming>
<bpmn:outgoing>Flow_0zrsh65</bpmn:outgoing> <bpmn:outgoing>Flow_0wgdxa6</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1yqkpgu" sourceRef="Gateway_18jn18b" targetRef="Activity_HSR" />
<bpmn:userTask id="Activity_HSR" name="Enter Health Safety Requirements" camunda:formKey="Lab Safety Plan"> <bpmn:userTask id="Activity_HSR" name="Enter Health Safety Requirements" camunda:formKey="Lab Safety Plan">
<bpmn:documentation>#### Health Safety Requirements: <bpmn:documentation>#### Health Safety Requirements:
Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/url?q=http://ehs.virginia.edu/files/Lab-Safety-Plan-During-COVID-19.docx&amp;source=gmail&amp;ust=1590687968958000&amp;usg=AFQjCNE83uGDFtxGkKaxjuXGhTocu-FDmw) to create and upload a copy of your laboratory policy statement to all members which includes at a minimum the following details: Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/url?q=http://ehs.virginia.edu/files/Lab-Safety-Plan-During-COVID-19.docx&amp;source=gmail&amp;ust=1590687968958000&amp;usg=AFQjCNE83uGDFtxGkKaxjuXGhTocu-FDmw) to create and upload a copy of your laboratory policy statement to all members which includes at a minimum the following details:
@ -551,10 +523,9 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
<camunda:formField id="LabSafetyPlan" label="Upload Lab Safety Plan" type="files" /> <camunda:formField id="LabSafetyPlan" label="Upload Lab Safety Plan" type="files" />
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_1yqkpgu</bpmn:incoming> <bpmn:incoming>Flow_0wgdxa6</bpmn:incoming>
<bpmn:outgoing>Flow_1ox5nv6</bpmn:outgoing> <bpmn:outgoing>Flow_0judgmp</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1c6m5wv" sourceRef="Gateway_18jn18b" targetRef="Activity_OtherReq" />
<bpmn:userTask id="Activity_OtherReq" name="Enter Other Requirements" camunda:formKey="Other Requirements"> <bpmn:userTask id="Activity_OtherReq" name="Enter Other Requirements" camunda:formKey="Other Requirements">
<bpmn:extensionElements> <bpmn:extensionElements>
<camunda:formData> <camunda:formData>
@ -598,8 +569,8 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_1c6m5wv</bpmn:incoming> <bpmn:incoming>Flow_0judgmp</bpmn:incoming>
<bpmn:outgoing>Flow_0qbi47d</bpmn:outgoing> <bpmn:outgoing>Flow_11uqavk</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:manualTask id="Activity_SubmitPlan" name="Acknowledge Plan Submission"> <bpmn:manualTask id="Activity_SubmitPlan" name="Acknowledge Plan Submission">
<bpmn:documentation>#### By submitting this request, you understand that every member listed in this form for on Grounds laboratory access will: <bpmn:documentation>#### By submitting this request, you understand that every member listed in this form for on Grounds laboratory access will:
@ -609,35 +580,28 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
<bpmn:incoming>Flow_08njvvi</bpmn:incoming> <bpmn:incoming>Flow_08njvvi</bpmn:incoming>
<bpmn:outgoing>Flow_0j4rs82</bpmn:outgoing> <bpmn:outgoing>Flow_0j4rs82</bpmn:outgoing>
</bpmn:manualTask> </bpmn:manualTask>
<bpmn:sequenceFlow id="Flow_0zrsh65" sourceRef="Activity_PWA" targetRef="Gateway_0sijkgx" />
<bpmn:sequenceFlow id="Flow_0tz5c2v" sourceRef="Activity_DistanceReq" targetRef="Gateway_0sijkgx" />
<bpmn:sequenceFlow id="Flow_1ox5nv6" sourceRef="Activity_HSR" targetRef="Gateway_0sijkgx" />
<bpmn:sequenceFlow id="Flow_0qbi47d" sourceRef="Activity_OtherReq" targetRef="Gateway_0sijkgx" />
<bpmn:sequenceFlow id="Flow_06873ag" sourceRef="Gateway_0sijkgx" targetRef="Activity_GenerateRRP" />
<bpmn:parallelGateway id="Gateway_0sijkgx">
<bpmn:incoming>Flow_0zrsh65</bpmn:incoming>
<bpmn:incoming>Flow_0tz5c2v</bpmn:incoming>
<bpmn:incoming>Flow_1ox5nv6</bpmn:incoming>
<bpmn:incoming>Flow_0qbi47d</bpmn:incoming>
<bpmn:outgoing>Flow_06873ag</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:scriptTask id="Activity_GenerateRRP" name="Generate RRP"> <bpmn:scriptTask id="Activity_GenerateRRP" name="Generate RRP">
<bpmn:documentation>#### Script Task <bpmn:documentation>#### Script Task
This step is internal to the system and do not require and user interaction</bpmn:documentation> This step is internal to the system and do not require and user interaction</bpmn:documentation>
<bpmn:incoming>Flow_06873ag</bpmn:incoming> <bpmn:incoming>Flow_11uqavk</bpmn:incoming>
<bpmn:outgoing>Flow_0aqgwvu</bpmn:outgoing> <bpmn:outgoing>Flow_0aqgwvu</bpmn:outgoing>
<bpmn:script>CompleteTemplate ResearchRampUpPlan.docx RESEARCH_RAMPUP</bpmn:script> <bpmn:script>CompleteTemplate ResearchRampUpPlan.docx RESEARCH_RAMPUP</bpmn:script>
</bpmn:scriptTask> </bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_0aqgwvu" sourceRef="Activity_GenerateRRP" targetRef="Activity_AcknowledgePlanReview" /> <bpmn:sequenceFlow id="Flow_0aqgwvu" sourceRef="Activity_GenerateRRP" targetRef="Activity_AcknowledgePlanReview" />
<bpmn:sequenceFlow id="Flow_0j4rs82" sourceRef="Activity_SubmitPlan" targetRef="Activity_0absozl" /> <bpmn:sequenceFlow id="Flow_0j4rs82" sourceRef="Activity_SubmitPlan" targetRef="Activity_0absozl" />
<bpmn:sequenceFlow id="Flow_07ge8uf" sourceRef="Activity_0absozl" targetRef="Activity_RequestStatus" /> <bpmn:sequenceFlow id="Flow_07ge8uf" sourceRef="Activity_0absozl" targetRef="Activity_1sq56an" />
<bpmn:sequenceFlow id="Flow_1ufh44h" sourceRef="Activity_RequestStatus" targetRef="Activity_AreaMonitorNotification" />
<bpmn:userTask id="Activity_RequestStatus" name="Check-on Request Status" camunda:formKey="Rquest Status"> <bpmn:userTask id="Activity_RequestStatus" name="Check-on Request Status" camunda:formKey="Rquest Status">
<bpmn:documentation>#### Approval Process <bpmn:documentation>#### Approval Process
The Research Ramp-up Plan and associated documents will be reviewed by{{ " " + ApprvlApprvrName1 }}{{ '.' if ApprvlApprvrName2 == 'n/a' else ' and ' + ApprvlApprvrName2 + '.' }} While waiting for approval, be sure that all required training has been completed and supplies secured. When the approval email notification is received, confirming the three questions below will allow you to proceed. The Research Ramp-up Plan and associated documents will be reviewed by{{ " " + ApprvlApprvrName1 }}{{ '.' if ApprvlApprvrName2 == 'n/a' else ' and ' + ApprvlApprvrName2 + '.' }} While waiting for approval, be sure that all required training has been completed and supplies secured. When the approval email notification is received, confirming the three questions below will allow you to proceed.
{%+ set ns = namespace() %}{% set ns.exclusive = 0 %}{% set ns.shared = 0 %}{% for es in exclusive %}{% if es.ExclusiveSpaceAMComputingID is none %}{% set ns.exclusive = ns.exclusive + 1 %}{% endif %}{% endfor %}{% for ss in shared %}{% if ss.SharedSpaceAMComputingID is none %}{% set ns.shared = ns.shared + 1 %}{% endif %}{% endfor %}
#### Test
Missing Exclusive: {{ ns.exclusive }}
Missing Shared: {{ ns.shared }}
If a rejection notification is received, go back to the first step that needs to be addressed and step through each subsequent form from that point.</bpmn:documentation> If a rejection notification is received, go back to the first step that needs to be addressed and step through each subsequent form from that point.</bpmn:documentation>
<bpmn:extensionElements> <bpmn:extensionElements>
@ -646,24 +610,94 @@ If a rejection notification is received, go back to the first step that needs to
<camunda:properties> <camunda:properties>
<camunda:property id="enum_type" value="checkbox" /> <camunda:property id="enum_type" value="checkbox" />
</camunda:properties> </camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
<camunda:value id="ApprovalNotificationReceived" name="Approval Notification Received?" /> <camunda:value id="ApprovalNotificationReceived" name="Approval Notification Received?" />
</camunda:formField> </camunda:formField>
<camunda:formField id="RequiredTraining" label="Please Confirm:" type="enum"> <camunda:formField id="RequiredTraining" label="Please Confirm:" type="enum">
<camunda:properties> <camunda:properties>
<camunda:property id="enum_type" value="checkbox" /> <camunda:property id="enum_type" value="checkbox" />
</camunda:properties> </camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
<camunda:value id="AllRequiredTraining" name="All Required Training Completed?" /> <camunda:value id="AllRequiredTraining" name="All Required Training Completed?" />
</camunda:formField> </camunda:formField>
<camunda:formField id="NeededSupplies" label="Please Confirm&#34;" type="enum"> <camunda:formField id="NeededSupplies" label="Please Confirm&#34;" type="enum">
<camunda:properties> <camunda:properties>
<camunda:property id="enum_type" value="checkbox" /> <camunda:property id="enum_type" value="checkbox" />
</camunda:properties> </camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
<camunda:value id="NeededSupplies" name="All Needed Supplies Secured?" /> <camunda:value id="NeededSupplies" name="All Needed Supplies Secured?" />
</camunda:formField> </camunda:formField>
<camunda:formField id="ExclusiveSpaceBuilding" label="Room No. &#38; Building Name" type="autocomplete">
<camunda:properties>
<camunda:property id="repeat" value="Exclusive" />
<camunda:property id="read_only" value="true" />
<camunda:property id="spreadsheet.name" value="Buildinglist.xls" />
<camunda:property id="spreadsheet.value.column" value="Value" />
<camunda:property id="spreadsheet.label.column" value="Building Name" />
<camunda:property id="repeat_title" value="Any missing Area Monitors for Exclusive Spaces must be entered" />
<camunda:property id="repeat_hide_expression" value="model.isAllExclusiveAreaMonitors" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="ExclusiveSpaceRoomID" label="Exclusive Space Room ID" type="string">
<camunda:properties>
<camunda:property id="repeat" value="Exclusive" />
<camunda:property id="read_only" value="true" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="ExclusiveSpaceType" label="Space Room Type" type="enum">
<camunda:properties>
<camunda:property id="read_only" value="true" />
<camunda:property id="repeat" value="Exclusive" />
</camunda:properties>
<camunda:value id="Lab" name="Lab" />
<camunda:value id="Office" name="Office" />
</camunda:formField>
<camunda:formField id="ExclusiveSpaceAMComputingID" label="Area Monitor" type="autocomplete">
<camunda:properties>
<camunda:property id="ldap.lookup" value="true" />
<camunda:property id="placeholder" value="wxy0z or Smith" />
<camunda:property id="repeat" value="Exclusive" />
</camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
</camunda:formField>
<camunda:formField id="SharedSpaceBuilding" label="Building Name" type="autocomplete">
<camunda:properties>
<camunda:property id="spreadsheet.name" value="Buildinglist.xls" />
<camunda:property id="spreadsheet.value.column" value="Value" />
<camunda:property id="spreadsheet.label.column" value="Building Name" />
<camunda:property id="repeat" value="Shared" />
<camunda:property id="repeat_title" value="Any missing Area Monitors for Shared Spaces must be entered" />
<camunda:property id="read_only" value="true" />
<camunda:property id="repeat_hide_expression" value="model.isAllSharedAreaMonitors" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="SharedSpaceRoomID" label="Shared Space Room ID" type="string">
<camunda:properties>
<camunda:property id="read_only" value="true" />
<camunda:property id="repeat" value="Shared" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="SharedSpaceAMComputingID" label="Area Monitor" type="autocomplete">
<camunda:properties>
<camunda:property id="ldap.lookup" value="true" />
<camunda:property id="repeat" value="Shared" />
<camunda:property id="placeholder" value="wxy0z or Smith" />
</camunda:properties>
<camunda:validation>
<camunda:constraint name="required" config="true" />
</camunda:validation>
</camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_07ge8uf</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0qc39tw</bpmn:outgoing>
<bpmn:outgoing>Flow_1ufh44h</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_05w8yd6" sourceRef="Activity_WhatNext" targetRef="EndEvent_09wp7av" /> <bpmn:sequenceFlow id="Flow_05w8yd6" sourceRef="Activity_WhatNext" targetRef="EndEvent_09wp7av" />
<bpmn:sequenceFlow id="Flow_08njvvi" sourceRef="Activity_ApprovalInfo" targetRef="Activity_SubmitPlan" /> <bpmn:sequenceFlow id="Flow_08njvvi" sourceRef="Activity_ApprovalInfo" targetRef="Activity_SubmitPlan" />
@ -698,7 +732,7 @@ Notify the Area Monitor for
#### Shared Space previously entered #### Shared Space previously entered
{%+ for ss in shared %}{{ ss.SharedSpaceRoomID + " " + ss.SharedSpaceBuilding.label }}{% if ss.SharedSpaceAMComputingID is none %}No Area Monitor entered{% else %}{{ ss.SharedSpaceAMComputingID.label }}{% endif %}{% if loop.last %}{% else %}, {% endif %}{% else %}No shared space entered.{% endfor %}</bpmn:documentation> {%+ for ss in shared %}{{ ss.SharedSpaceRoomID + " " + ss.SharedSpaceBuilding.label }}{% if ss.SharedSpaceAMComputingID is none %}No Area Monitor entered{% else %}{{ ss.SharedSpaceAMComputingID.label }}{% endif %}{% if loop.last %}{% else %}, {% endif %}{% else %}No shared space entered.{% endfor %}</bpmn:documentation>
<bpmn:incoming>Flow_1ufh44h</bpmn:incoming> <bpmn:incoming>SequenceFlow_0qc39tw</bpmn:incoming>
<bpmn:outgoing>Flow_0cpmvcw</bpmn:outgoing> <bpmn:outgoing>Flow_0cpmvcw</bpmn:outgoing>
</bpmn:manualTask> </bpmn:manualTask>
<bpmn:scriptTask id="Activity_0absozl" name="Execute Plan Submission"> <bpmn:scriptTask id="Activity_0absozl" name="Execute Plan Submission">
@ -710,18 +744,16 @@ This step is internal to the system and do not require and user interaction</bpm
<bpmn:outgoing>Flow_07ge8uf</bpmn:outgoing> <bpmn:outgoing>Flow_07ge8uf</bpmn:outgoing>
<bpmn:script>RequestApproval ApprvlApprvr1 ApprvlApprvr2</bpmn:script> <bpmn:script>RequestApproval ApprvlApprvr1 ApprvlApprvr2</bpmn:script>
</bpmn:scriptTask> </bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_1v7r1tg" sourceRef="Activity_1u58hox" targetRef="Gateway_0frfdnc" />
<bpmn:scriptTask id="Activity_1u58hox" name="Update Request"> <bpmn:scriptTask id="Activity_1u58hox" name="Update Request">
<bpmn:documentation>#### Script Task <bpmn:documentation>#### Script Task
This step is internal to the system and do not require and user interaction</bpmn:documentation> This step is internal to the system and do not require and user interaction</bpmn:documentation>
<bpmn:incoming>Flow_16y8glw</bpmn:incoming> <bpmn:incoming>Flow_16y8glw</bpmn:incoming>
<bpmn:outgoing>Flow_1v7r1tg</bpmn:outgoing> <bpmn:outgoing>Flow_0uc4o6c</bpmn:outgoing>
<bpmn:script>UpdateStudy title:PIComputingID.label pi:PIComputingID.value</bpmn:script> <bpmn:script>UpdateStudy title:PIComputingID.label pi:PIComputingID.value</bpmn:script>
</bpmn:scriptTask> </bpmn:scriptTask>
<bpmn:sequenceFlow id="Flow_097fpi3" sourceRef="PersonnelWeeklyScheduleTask" targetRef="Gateway_18jn18b" /> <bpmn:userTask id="PersonnelSchedule" name="Upload Weekly Personnel Schedule(s)" camunda:formKey="Personnel Weekly Schedule">
<bpmn:userTask id="PersonnelWeeklyScheduleTask" name="Upload Weekly Personnel Schedule(s)" camunda:formKey="Personnel Schedule">
<bpmn:documentation>#### Weekly Personnel Schedule(s) <bpmn:documentation>#### Weekly Personnel Schedule(s)
Provide initial weekly schedule(s) for the PI and all personnel for whom access has been requested, indicating each space they will be working in and all shifts, if applicable. Provide initial weekly schedule(s) for the PI and all personnel for whom access has been requested, indicating each space they will be working in and all shifts, if applicable.
@ -741,236 +773,216 @@ Provide initial weekly schedule(s) for the PI and all personnel for whom access
</camunda:formField> </camunda:formField>
</camunda:formData> </camunda:formData>
</bpmn:extensionElements> </bpmn:extensionElements>
<bpmn:incoming>Flow_1nbjr72</bpmn:incoming> <bpmn:incoming>Flow_1yxaewj</bpmn:incoming>
<bpmn:outgoing>Flow_097fpi3</bpmn:outgoing> <bpmn:outgoing>Flow_1itd8db</bpmn:outgoing>
</bpmn:userTask> </bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0uc4o6c" sourceRef="Activity_1u58hox" targetRef="Activity_ExclusiveSpace" />
<bpmn:sequenceFlow id="Flow_0o4tg9g" sourceRef="Activity_ExclusiveSpace" targetRef="Activity_SharedSpaceInfo" />
<bpmn:sequenceFlow id="Flow_1n69wsr" sourceRef="Activity_SharedSpaceInfo" targetRef="UserTask_CoreResource" />
<bpmn:sequenceFlow id="Flow_13pusfu" sourceRef="UserTask_CoreResource" targetRef="Activity_nonUVASpaces" />
<bpmn:sequenceFlow id="Flow_1yxaewj" sourceRef="Activity_Personnel" targetRef="PersonnelSchedule" />
<bpmn:sequenceFlow id="Flow_1itd8db" sourceRef="PersonnelSchedule" targetRef="Activity_DistanceReq" />
<bpmn:sequenceFlow id="Flow_1lo964l" sourceRef="Activity_DistanceReq" targetRef="Activity_PWA" />
<bpmn:sequenceFlow id="Flow_0wgdxa6" sourceRef="Activity_PWA" targetRef="Activity_HSR" />
<bpmn:sequenceFlow id="Flow_0judgmp" sourceRef="Activity_HSR" targetRef="Activity_OtherReq" />
<bpmn:sequenceFlow id="Flow_11uqavk" sourceRef="Activity_OtherReq" targetRef="Activity_GenerateRRP" />
<bpmn:sequenceFlow id="Flow_0peeyne" sourceRef="Activity_1sq56an" targetRef="Activity_14xt8is" />
<bpmn:businessRuleTask id="Activity_1sq56an" name="Check Exclusive Area Monitors" camunda:decisionRef="Decision_ExclusiveAMCheck">
<bpmn:documentation>#### Business Rule Task
This step is internal to the system and do not require and user interaction</bpmn:documentation>
<bpmn:incoming>Flow_07ge8uf</bpmn:incoming>
<bpmn:outgoing>Flow_0peeyne</bpmn:outgoing>
</bpmn:businessRuleTask>
<bpmn:sequenceFlow id="Flow_0tqna2m" sourceRef="Activity_14xt8is" targetRef="Activity_RequestStatus" />
<bpmn:businessRuleTask id="Activity_14xt8is" name="Check Shared Area Monitors" camunda:decisionRef="Decision_SharedAMCheck">
<bpmn:documentation>#### Business Rule Task
This step is internal to the system and do not require and user interaction</bpmn:documentation>
<bpmn:incoming>Flow_0peeyne</bpmn:incoming>
<bpmn:outgoing>Flow_0tqna2m</bpmn:outgoing>
</bpmn:businessRuleTask>
<bpmn:sequenceFlow id="Flow_0hc1r8a" sourceRef="Activity_nonUVASpaces" targetRef="Activity_Personnel" />
<bpmn:sequenceFlow id="SequenceFlow_0qc39tw" sourceRef="Activity_RequestStatus" targetRef="Activity_AreaMonitorNotification" />
</bpmn:process> </bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0ssahs9"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0ssahs9">
<bpmndi:BPMNEdge id="Flow_097fpi3_di" bpmnElement="Flow_097fpi3"> <bpmndi:BPMNEdge id="SequenceFlow_0qc39tw_di" bpmnElement="SequenceFlow_0qc39tw">
<di:waypoint x="1290" y="307" /> <di:waypoint x="3290" y="117" />
<di:waypoint x="1335" y="307" /> <di:waypoint x="3330" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1v7r1tg_di" bpmnElement="Flow_1v7r1tg"> <bpmndi:BPMNEdge id="Flow_0hc1r8a_di" bpmnElement="Flow_0hc1r8a">
<di:waypoint x="630" y="307" /> <di:waypoint x="1260" y="117" />
<di:waypoint x="685" y="307" /> <di:waypoint x="1310" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tqna2m_di" bpmnElement="Flow_0tqna2m">
<di:waypoint x="3140" y="117" />
<di:waypoint x="3190" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0peeyne_di" bpmnElement="Flow_0peeyne">
<di:waypoint x="2990" y="117" />
<di:waypoint x="3040" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_11uqavk_di" bpmnElement="Flow_11uqavk">
<di:waypoint x="2120" y="117" />
<di:waypoint x="2170" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0judgmp_di" bpmnElement="Flow_0judgmp">
<di:waypoint x="1980" y="117" />
<di:waypoint x="2020" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0wgdxa6_di" bpmnElement="Flow_0wgdxa6">
<di:waypoint x="1840" y="117" />
<di:waypoint x="1880" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1lo964l_di" bpmnElement="Flow_1lo964l">
<di:waypoint x="1700" y="117" />
<di:waypoint x="1740" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1itd8db_di" bpmnElement="Flow_1itd8db">
<di:waypoint x="1550" y="117" />
<di:waypoint x="1600" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yxaewj_di" bpmnElement="Flow_1yxaewj">
<di:waypoint x="1410" y="117" />
<di:waypoint x="1450" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_13pusfu_di" bpmnElement="Flow_13pusfu">
<di:waypoint x="1100" y="117" />
<di:waypoint x="1160" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1n69wsr_di" bpmnElement="Flow_1n69wsr">
<di:waypoint x="950" y="117" />
<di:waypoint x="1000" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0o4tg9g_di" bpmnElement="Flow_0o4tg9g">
<di:waypoint x="790" y="117" />
<di:waypoint x="850" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0uc4o6c_di" bpmnElement="Flow_0uc4o6c">
<di:waypoint x="630" y="117" />
<di:waypoint x="690" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0cpmvcw_di" bpmnElement="Flow_0cpmvcw"> <bpmndi:BPMNEdge id="Flow_0cpmvcw_di" bpmnElement="Flow_0cpmvcw">
<di:waypoint x="2600" y="307" /> <di:waypoint x="3430" y="117" />
<di:waypoint x="2650" y="307" /> <di:waypoint x="3480" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_08njvvi_di" bpmnElement="Flow_08njvvi"> <bpmndi:BPMNEdge id="Flow_08njvvi_di" bpmnElement="Flow_08njvvi">
<di:waypoint x="2030" y="307" /> <di:waypoint x="2560" y="117" />
<di:waypoint x="2060" y="307" /> <di:waypoint x="2610" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_05w8yd6_di" bpmnElement="Flow_05w8yd6"> <bpmndi:BPMNEdge id="Flow_05w8yd6_di" bpmnElement="Flow_05w8yd6">
<di:waypoint x="2750" y="307" /> <di:waypoint x="3580" y="117" />
<di:waypoint x="2822" y="307" /> <di:waypoint x="3652" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ufh44h_di" bpmnElement="Flow_1ufh44h">
<di:waypoint x="2460" y="307" />
<di:waypoint x="2500" y="307" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_07ge8uf_di" bpmnElement="Flow_07ge8uf"> <bpmndi:BPMNEdge id="Flow_07ge8uf_di" bpmnElement="Flow_07ge8uf">
<di:waypoint x="2310" y="307" /> <di:waypoint x="2850" y="117" />
<di:waypoint x="2360" y="307" /> <di:waypoint x="2890" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0j4rs82_di" bpmnElement="Flow_0j4rs82"> <bpmndi:BPMNEdge id="Flow_0j4rs82_di" bpmnElement="Flow_0j4rs82">
<di:waypoint x="2160" y="307" /> <di:waypoint x="2710" y="117" />
<di:waypoint x="2210" y="307" /> <di:waypoint x="2750" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0aqgwvu_di" bpmnElement="Flow_0aqgwvu"> <bpmndi:BPMNEdge id="Flow_0aqgwvu_di" bpmnElement="Flow_0aqgwvu">
<di:waypoint x="1770" y="307" /> <di:waypoint x="2270" y="117" />
<di:waypoint x="1800" y="307" /> <di:waypoint x="2310" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_06873ag_di" bpmnElement="Flow_06873ag">
<di:waypoint x="1625" y="307" />
<di:waypoint x="1670" y="307" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qbi47d_di" bpmnElement="Flow_0qbi47d">
<di:waypoint x="1530" y="510" />
<di:waypoint x="1600" y="510" />
<di:waypoint x="1600" y="332" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1ox5nv6_di" bpmnElement="Flow_1ox5nv6">
<di:waypoint x="1530" y="380" />
<di:waypoint x="1600" y="380" />
<di:waypoint x="1600" y="332" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tz5c2v_di" bpmnElement="Flow_0tz5c2v">
<di:waypoint x="1530" y="120" />
<di:waypoint x="1600" y="120" />
<di:waypoint x="1600" y="282" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0zrsh65_di" bpmnElement="Flow_0zrsh65">
<di:waypoint x="1530" y="240" />
<di:waypoint x="1600" y="240" />
<di:waypoint x="1600" y="282" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1c6m5wv_di" bpmnElement="Flow_1c6m5wv">
<di:waypoint x="1360" y="332" />
<di:waypoint x="1360" y="510" />
<di:waypoint x="1430" y="510" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yqkpgu_di" bpmnElement="Flow_1yqkpgu">
<di:waypoint x="1360" y="332" />
<di:waypoint x="1360" y="380" />
<di:waypoint x="1430" y="380" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0mkh1wn_di" bpmnElement="Flow_0mkh1wn">
<di:waypoint x="1360" y="282" />
<di:waypoint x="1360" y="240" />
<di:waypoint x="1430" y="240" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0p2r1bo_di" bpmnElement="Flow_0p2r1bo">
<di:waypoint x="1360" y="282" />
<di:waypoint x="1360" y="120" />
<di:waypoint x="1430" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1nbjr72_di" bpmnElement="Flow_1nbjr72">
<di:waypoint x="1150" y="307" />
<di:waypoint x="1190" y="307" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1eiud85_di" bpmnElement="Flow_1eiud85">
<di:waypoint x="995" y="307" />
<di:waypoint x="1050" y="307" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0zz2hbq_di" bpmnElement="Flow_0zz2hbq">
<di:waypoint x="890" y="510" />
<di:waypoint x="970" y="510" />
<di:waypoint x="970" y="332" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ya8hw8_di" bpmnElement="Flow_0ya8hw8">
<di:waypoint x="710" y="332" />
<di:waypoint x="710" y="510" />
<di:waypoint x="790" y="510" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_12ie6w0_di" bpmnElement="Flow_12ie6w0">
<di:waypoint x="890" y="370" />
<di:waypoint x="970" y="370" />
<di:waypoint x="970" y="332" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_15zy1q7_di" bpmnElement="Flow_15zy1q7">
<di:waypoint x="710" y="332" />
<di:waypoint x="710" y="370" />
<di:waypoint x="790" y="370" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tk64b6_di" bpmnElement="Flow_0tk64b6">
<di:waypoint x="890" y="110" />
<di:waypoint x="970" y="110" />
<di:waypoint x="970" y="282" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0qf2y84_di" bpmnElement="Flow_0qf2y84">
<di:waypoint x="710" y="282" />
<di:waypoint x="710" y="110" />
<di:waypoint x="790" y="110" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_16y8glw_di" bpmnElement="Flow_16y8glw"> <bpmndi:BPMNEdge id="Flow_16y8glw_di" bpmnElement="Flow_16y8glw">
<di:waypoint x="480" y="307" /> <di:waypoint x="480" y="117" />
<di:waypoint x="530" y="307" /> <di:waypoint x="530" y="117" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_16342pm_di" bpmnElement="Flow_16342pm">
<di:waypoint x="890" y="240" />
<di:waypoint x="970" y="240" />
<di:waypoint x="970" y="282" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_19xeq76_di" bpmnElement="Flow_19xeq76">
<di:waypoint x="710" y="282" />
<di:waypoint x="710" y="240" />
<di:waypoint x="790" y="240" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1e2qi9s_di" bpmnElement="Flow_1e2qi9s"> <bpmndi:BPMNEdge id="Flow_1e2qi9s_di" bpmnElement="Flow_1e2qi9s">
<di:waypoint x="1900" y="307" /> <di:waypoint x="2410" y="117" />
<di:waypoint x="1930" y="307" /> <di:waypoint x="2460" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_05ja25w_di" bpmnElement="SequenceFlow_05ja25w"> <bpmndi:BPMNEdge id="SequenceFlow_05ja25w_di" bpmnElement="SequenceFlow_05ja25w">
<di:waypoint x="168" y="307" /> <di:waypoint x="168" y="117" />
<di:waypoint x="230" y="307" /> <di:waypoint x="230" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_0h50bp3_di" bpmnElement="SequenceFlow_0h50bp3"> <bpmndi:BPMNEdge id="SequenceFlow_0h50bp3_di" bpmnElement="SequenceFlow_0h50bp3">
<di:waypoint x="330" y="307" /> <di:waypoint x="330" y="117" />
<di:waypoint x="380" y="307" /> <di:waypoint x="380" y="117" />
</bpmndi:BPMNEdge> </bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"> <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="132" y="289" width="36" height="36" /> <dc:Bounds x="132" y="99" width="36" height="36" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ManualTask_1ofy9yz_di" bpmnElement="ManualTask_Instructions"> <bpmndi:BPMNShape id="ManualTask_1ofy9yz_di" bpmnElement="ManualTask_Instructions">
<dc:Bounds x="230" y="267" width="100" height="80" /> <dc:Bounds x="230" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_0xdpoxl_di" bpmnElement="Activity-PI_Info"> <bpmndi:BPMNShape id="UserTask_0xdpoxl_di" bpmnElement="Activity-PI_Info">
<dc:Bounds x="380" y="267" width="100" height="80" /> <dc:Bounds x="380" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_0ecab9j_di" bpmnElement="Personnel"> <bpmndi:BPMNShape id="UserTask_0ecab9j_di" bpmnElement="Activity_Personnel">
<dc:Bounds x="1050" y="267" width="100" height="80" /> <dc:Bounds x="1310" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_0l8vxty_di" bpmnElement="UserTask_CoreResource"> <bpmndi:BPMNShape id="UserTask_0l8vxty_di" bpmnElement="UserTask_CoreResource">
<dc:Bounds x="790" y="330" width="100" height="80" /> <dc:Bounds x="1000" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_09wp7av_di" bpmnElement="EndEvent_09wp7av"> <bpmndi:BPMNShape id="EndEvent_09wp7av_di" bpmnElement="EndEvent_09wp7av">
<dc:Bounds x="2822" y="289" width="36" height="36" /> <dc:Bounds x="3652" y="99" width="36" height="36" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1mg5lp9_di" bpmnElement="Activity_AcknowledgePlanReview"> <bpmndi:BPMNShape id="Activity_1mg5lp9_di" bpmnElement="Activity_AcknowledgePlanReview">
<dc:Bounds x="1800" y="267" width="100" height="80" /> <dc:Bounds x="2310" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1xgrlzr_di" bpmnElement="Activity_SharedSpaceInfo"> <bpmndi:BPMNShape id="Activity_1xgrlzr_di" bpmnElement="Activity_SharedSpaceInfo">
<dc:Bounds x="790" y="200" width="100" height="80" /> <dc:Bounds x="850" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0tn2il3_di" bpmnElement="Gateway_0frfdnc">
<dc:Bounds x="685" y="282" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1o1fcbg_di" bpmnElement="Gateway_1vj4zd3">
<dc:Bounds x="945" y="282" width="50" height="50" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1jefdme_di" bpmnElement="Activity_ExclusiveSpace"> <bpmndi:BPMNShape id="Activity_1jefdme_di" bpmnElement="Activity_ExclusiveSpace">
<dc:Bounds x="790" y="70" width="100" height="80" /> <dc:Bounds x="690" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0ysw6zo_di" bpmnElement="Activity_nonUVASpaces"> <bpmndi:BPMNShape id="Activity_0ysw6zo_di" bpmnElement="Activity_nonUVASpaces">
<dc:Bounds x="790" y="470" width="100" height="80" /> <dc:Bounds x="1160" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1xag6qb_di" bpmnElement="Activity_DistanceReq"> <bpmndi:BPMNShape id="Activity_1xag6qb_di" bpmnElement="Activity_DistanceReq">
<dc:Bounds x="1430" y="80" width="100" height="80" /> <dc:Bounds x="1600" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0yof76x_di" bpmnElement="Gateway_18jn18b">
<dc:Bounds x="1335" y="282" width="50" height="50" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_166b0qq_di" bpmnElement="Activity_PWA"> <bpmndi:BPMNShape id="Activity_166b0qq_di" bpmnElement="Activity_PWA">
<dc:Bounds x="1430" y="200" width="100" height="80" /> <dc:Bounds x="1740" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0byj9mp_di" bpmnElement="Activity_HSR"> <bpmndi:BPMNShape id="Activity_0byj9mp_di" bpmnElement="Activity_HSR">
<dc:Bounds x="1430" y="340" width="100" height="80" /> <dc:Bounds x="1880" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0j0p13i_di" bpmnElement="Activity_OtherReq"> <bpmndi:BPMNShape id="Activity_0j0p13i_di" bpmnElement="Activity_OtherReq">
<dc:Bounds x="1430" y="470" width="100" height="80" /> <dc:Bounds x="2020" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1h30fo8_di" bpmnElement="Activity_SubmitPlan"> <bpmndi:BPMNShape id="Activity_1h30fo8_di" bpmnElement="Activity_SubmitPlan">
<dc:Bounds x="2060" y="267" width="100" height="80" /> <dc:Bounds x="2610" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_03lxnzh_di" bpmnElement="Gateway_0sijkgx">
<dc:Bounds x="1575" y="282" width="50" height="50" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_117owwi_di" bpmnElement="Activity_GenerateRRP"> <bpmndi:BPMNShape id="Activity_117owwi_di" bpmnElement="Activity_GenerateRRP">
<dc:Bounds x="1670" y="267" width="100" height="80" /> <dc:Bounds x="2170" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0fxf44t_di" bpmnElement="Activity_RequestStatus"> <bpmndi:BPMNShape id="Activity_0fxf44t_di" bpmnElement="Activity_RequestStatus">
<dc:Bounds x="2360" y="267" width="100" height="80" /> <dc:Bounds x="3190" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_080o38p_di" bpmnElement="Activity_ApprovalInfo"> <bpmndi:BPMNShape id="Activity_080o38p_di" bpmnElement="Activity_ApprovalInfo">
<dc:Bounds x="1930" y="267" width="100" height="80" /> <dc:Bounds x="2460" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0wuukfn_di" bpmnElement="Activity_WhatNext"> <bpmndi:BPMNShape id="Activity_0wuukfn_di" bpmnElement="Activity_WhatNext">
<dc:Bounds x="2650" y="267" width="100" height="80" /> <dc:Bounds x="3480" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0js9ww9_di" bpmnElement="Activity_AreaMonitorNotification"> <bpmndi:BPMNShape id="Activity_0js9ww9_di" bpmnElement="Activity_AreaMonitorNotification">
<dc:Bounds x="2500" y="267" width="100" height="80" /> <dc:Bounds x="3330" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0wnn9de_di" bpmnElement="Activity_0absozl"> <bpmndi:BPMNShape id="Activity_0wnn9de_di" bpmnElement="Activity_0absozl">
<dc:Bounds x="2210" y="267" width="100" height="80" /> <dc:Bounds x="2750" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0f0ak6p_di" bpmnElement="Activity_1u58hox"> <bpmndi:BPMNShape id="Activity_0f0ak6p_di" bpmnElement="Activity_1u58hox">
<dc:Bounds x="530" y="267" width="100" height="80" /> <dc:Bounds x="530" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_11iexzh_di" bpmnElement="PersonnelWeeklyScheduleTask"> <bpmndi:BPMNShape id="Activity_11iexzh_di" bpmnElement="PersonnelSchedule">
<dc:Bounds x="1190" y="267" width="100" height="80" /> <dc:Bounds x="1450" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0r358ps_di" bpmnElement="Activity_1sq56an">
<dc:Bounds x="2890" y="77" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1i34vt6_di" bpmnElement="Activity_14xt8is">
<dc:Bounds x="3040" y="77" width="100" height="80" />
</bpmndi:BPMNShape> </bpmndi:BPMNShape>
</bpmndi:BPMNPlane> </bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram> </bpmndi:BPMNDiagram>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" id="Definitions_06veek1" name="DRD" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<decision id="Decision_SharedAMCheck" name="Shared AM Check">
<decisionTable id="decisionTable_1">
<input id="InputClause_1koybx6" label="How Many Shared Spaces">
<inputExpression id="LiteralExpression_1mjo0y4" typeRef="integer" expressionLanguage="python">
<text>'shared' in locals() and len(shared)</text>
</inputExpression>
</input>
<input id="input_1" label="Number Without Area Monitor">
<inputExpression id="inputExpression_1" typeRef="integer" expressionLanguage="python">
<text>sum([1 for x in exclusive if x.get('SharedSpaceAMComputingID',None) == None])</text>
</inputExpression>
</input>
<output id="output_1" label="All Possible Shared Area Monitors Entered" name="isAllSharedAreaMonitors" typeRef="boolean" />
<rule id="DecisionRule_07162mr">
<description>No shared spaces without Area Monitor</description>
<inputEntry id="UnaryTests_1p4ab2l">
<text>&gt;0</text>
</inputEntry>
<inputEntry id="UnaryTests_1jqxc3u">
<text>0</text>
</inputEntry>
<outputEntry id="LiteralExpression_16l50ps">
<text>true</text>
</outputEntry>
</rule>
<rule id="DecisionRule_0ifa4wu">
<description>One or more shared space without an Area Monitor</description>
<inputEntry id="UnaryTests_06bujee">
<text>&gt;0</text>
</inputEntry>
<inputEntry id="UnaryTests_0szbwxc">
<text>&gt; 0</text>
</inputEntry>
<outputEntry id="LiteralExpression_0td8sa6">
<text>false</text>
</outputEntry>
</rule>
<rule id="DecisionRule_1uh85sk">
<description>No shared spaces entered</description>
<inputEntry id="UnaryTests_15grk62">
<text>0</text>
</inputEntry>
<inputEntry id="UnaryTests_1gaiomm">
<text></text>
</inputEntry>
<outputEntry id="LiteralExpression_1iep8ai">
<text>true</text>
</outputEntry>
</rule>
</decisionTable>
</decision>
</definitions>

View File

@ -45,7 +45,7 @@ class TestApprovals(BaseTest):
study=self.study, study=self.study,
workflow=self.workflow, workflow=self.workflow,
approver_uid='arc93', approver_uid='arc93',
status=ApprovalStatus.WAITING.value, status=ApprovalStatus.PENDING.value,
version=1 version=1
) )
session.add(self.approval) session.add(self.approval)
@ -54,7 +54,7 @@ class TestApprovals(BaseTest):
study=self.study, study=self.study,
workflow=self.workflow, workflow=self.workflow,
approver_uid='dhf8r', approver_uid='dhf8r',
status=ApprovalStatus.WAITING.value, status=ApprovalStatus.PENDING.value,
version=1 version=1
) )
session.add(self.approval_2) session.add(self.approval_2)
@ -98,7 +98,7 @@ class TestApprovals(BaseTest):
data = dict(APPROVAL_PAYLOAD) data = dict(APPROVAL_PAYLOAD)
data['id'] = approval_id data['id'] = approval_id
self.assertEqual(self.approval.status, ApprovalStatus.WAITING.value) self.assertEqual(self.approval.status, ApprovalStatus.PENDING.value)
rv = self.app.put(f'/v1.0/approval/{approval_id}', rv = self.app.put(f'/v1.0/approval/{approval_id}',
content_type="application/json", content_type="application/json",

View File

@ -1,5 +1,6 @@
import json import json
from tests.base_test import BaseTest from tests.base_test import BaseTest
from datetime import datetime, timezone from datetime import datetime, timezone
from unittest.mock import patch from unittest.mock import patch
@ -8,8 +9,9 @@ from crc.models.protocol_builder import ProtocolBuilderStatus, \
ProtocolBuilderStudySchema ProtocolBuilderStudySchema
from crc.models.stats import TaskEventModel from crc.models.stats import TaskEventModel
from crc.models.study import StudyModel, StudySchema from crc.models.study import StudyModel, StudySchema
from crc.models.workflow import WorkflowSpecModel, WorkflowModel, WorkflowSpecCategoryModel from crc.models.workflow import WorkflowSpecModel, WorkflowModel
from crc.services.protocol_builder import ProtocolBuilderService from crc.services.file_service import FileService
from crc.services.workflow_processor import WorkflowProcessor
class TestStudyApi(BaseTest): class TestStudyApi(BaseTest):
@ -68,6 +70,34 @@ class TestStudyApi(BaseTest):
self.assertEqual(0, workflow["total_tasks"]) self.assertEqual(0, workflow["total_tasks"])
self.assertEqual(0, workflow["completed_tasks"]) self.assertEqual(0, workflow["completed_tasks"])
def test_get_study_has_details_about_files(self):
# Set up the study and attach a file to it.
self.load_example_data()
self.create_reference_document()
workflow = self.create_workflow('file_upload_form')
processor = WorkflowProcessor(workflow)
task = processor.next_task()
irb_code = "UVACompl_PRCAppr" # The first file referenced in pb required docs.
FileService.add_workflow_file(workflow_id=workflow.id,
name="anything.png", content_type="png",
binary_data=b'1234', irb_doc_code=irb_code)
api_response = self.app.get('/v1.0/study/%i' % workflow.study_id,
headers=self.logged_in_headers(), content_type="application/json")
self.assert_success(api_response)
study = StudySchema().loads(api_response.get_data(as_text=True))
self.assertEquals(1, len(study.files))
self.assertEquals("UVA Compliance/PRC Approval", study.files[0]["category"])
self.assertEquals("Cancer Center's PRC Approval Form", study.files[0]["description"])
self.assertEquals("UVA Compliance/PRC Approval.png", study.files[0]["download_name"])
# TODO: WRITE A TEST FOR STUDY FILES
def test_get_study_has_details_about_approvals(self):
# TODO: WRITE A TEST FOR STUDY APPROVALS
pass
def test_add_study(self): def test_add_study(self):
self.load_example_data() self.load_example_data()
study = self.add_test_study() study = self.add_test_study()