updates using new navigation from spiff workflow's navigation branch, all tests passing.

This commit is contained in:
Dan 2020-12-04 17:56:12 -05:00
parent aca1fb366b
commit 93b12a8e82
9 changed files with 491 additions and 356 deletions

View File

@ -39,7 +39,7 @@ requests = "*"
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
sphinx = "*"
swagger-ui-bundle = "*"
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "bug/navigation"}
webtest = "*"
werkzeug = "*"
xlrd = "*"

49
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "621d57ec513f24c665dd34e08ae5a19fc27784e87c55bb4d2a91a1d48a473081"
"sha256": "1e41c4486a74db3ee30b7fd4572b0cc54cfbe1bc1e6246b855748ec78db6cc1e"
},
"pipfile-spec": 6,
"requires": {
@ -33,10 +33,10 @@
},
"aniso8601": {
"hashes": [
"sha256:529dcb1f5f26ee0df6c0a1ee84b7b27197c3c50fc3a6321d66c544689237d072",
"sha256:c033f63d028b9a58e3ab0c2c7d0532ab4bfa7452bfc788fbfe3ddabd327b181a"
"sha256:246bf8d3611527030889e6df970878969d3a2f760ba3eb694fa1fb10e6ce53f9",
"sha256:51047d4fb51d7b8afd522b70f2d21a1b2487cbb7f7bd84ea852e9aa7808e7704"
],
"version": "==8.0.0"
"version": "==8.1.0"
},
"attrs": {
"hashes": [
@ -108,12 +108,14 @@
"sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
"sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
"sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
"sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01",
"sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
"sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
"sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
"sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
"sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
"sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
"sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e",
"sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
"sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
"sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
@ -548,10 +550,10 @@
},
"packaging": {
"hashes": [
"sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
"sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
"sha256:05af3bb85d320377db281cf254ab050e1a7ebcbf5410685a9a407e18a1f81236",
"sha256:eb41423378682dadb7166144a4926e443093863024de508ca5c9737d6bc08376"
],
"version": "==20.4"
"version": "==20.7"
},
"pandas": {
"hashes": [
@ -640,11 +642,11 @@
},
"pygithub": {
"hashes": [
"sha256:776befaddab9d8fddd525d52a6ca1ac228cf62b5b1e271836d766f4925e1452e",
"sha256:8ad656bf79958e775ec59f7f5a3dbcbadac12147ae3dc42708b951064096af15"
"sha256:053f1b8d553a344ebd3ca3972765d923ee7e8ecc3ea55bd203683f164348fa1a",
"sha256:14c96d55e3c0e295598e52fbbbf2a7862a293723482ae9000cb9c816faab4fb4"
],
"index": "pypi",
"version": "==1.53"
"version": "==1.54"
},
"pygments": {
"hashes": [
@ -746,11 +748,11 @@
},
"requests": {
"hashes": [
"sha256:7f1a0b932f4a60a1a65caa4263921bb7d9ee911957e0ae4a23a6dd08185ad5f8",
"sha256:e786fa28d8c9154e6a4de5d46a1d921b8749f8b74e28bde23768e5e16eece998"
"sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b",
"sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"
],
"index": "pypi",
"version": "==2.25.0"
"version": "==2.24.0"
},
"sentry-sdk": {
"extras": [
@ -837,7 +839,7 @@
},
"spiffworkflow": {
"git": "https://github.com/sartography/SpiffWorkflow.git",
"ref": "6b2ed24bb340ebd31049312bd321f66ebf7b6b26"
"ref": "cdab930848493d74250224f1956177fee231a5b7"
},
"sqlalchemy": {
"hashes": [
@ -892,10 +894,10 @@
},
"urllib3": {
"hashes": [
"sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08",
"sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"
"sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2",
"sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e"
],
"version": "==1.26.2"
"version": "==1.25.11"
},
"waitress": {
"hashes": [
@ -1014,10 +1016,10 @@
},
"packaging": {
"hashes": [
"sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8",
"sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"
"sha256:05af3bb85d320377db281cf254ab050e1a7ebcbf5410685a9a407e18a1f81236",
"sha256:eb41423378682dadb7166144a4926e443093863024de508ca5c9737d6bc08376"
],
"version": "==20.4"
"version": "==20.7"
},
"pbr": {
"hashes": [
@ -1056,13 +1058,6 @@
"index": "pypi",
"version": "==6.1.2"
},
"six": {
"hashes": [
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
],
"version": "==1.15.0"
},
"toml": {
"hashes": [
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",

View File

@ -1,13 +1,13 @@
import uuid
from SpiffWorkflow.util.deep_merge import DeepMerge
from flask import g
from crc import session, app
from crc import session
from crc.api.common import ApiError, ApiErrorSchema
from crc.models.api_models import WorkflowApi, WorkflowApiSchema, NavigationItem, NavigationItemSchema
from crc.models.api_models import WorkflowApiSchema
from crc.models.file import FileModel, LookupDataSchema
from crc.models.study import StudyModel, WorkflowMetadata
from crc.models.task_event import TaskEventModel, TaskEventModelSchema, TaskEvent, TaskEventSchema
from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema
from crc.models.workflow import WorkflowModel, WorkflowSpecModelSchema, WorkflowSpecModel, WorkflowSpecCategoryModel, \
WorkflowSpecCategoryModelSchema
from crc.services.file_service import FileService

View File

@ -1,6 +1,7 @@
import enum
import marshmallow
from SpiffWorkflow.navigation import NavItem
from marshmallow import INCLUDE
from marshmallow_enum import EnumField
@ -15,22 +16,6 @@ class MultiInstanceType(enum.Enum):
sequential = "sequential"
class NavigationItem(object):
def __init__(self, id, task_id, name, title, backtracks, level, indent, child_count, state, is_decision,
task=None, lane=None):
self.id = id
self.task_id = task_id
self.name = name,
self.title = title
self.backtracks = backtracks
self.level = level
self.indent = indent
self.child_count = child_count
self.state = state
self.is_decision = is_decision
self.task = task
self.lane = lane
class Task(object):
##########################################################################
@ -158,15 +143,23 @@ class TaskSchema(ma.Schema):
class NavigationItemSchema(ma.Schema):
class Meta:
fields = ["id", "task_id", "name", "title", "backtracks", "level", "indent", "child_count", "state",
"is_decision", "task", "lane"]
fields = ["spec_id", "name", "spec_type", "task_id", "description", "backtracks", "indent",
"lane", "state"]
unknown = INCLUDE
task = marshmallow.fields.Nested(TaskSchema, dump_only=True, required=False, allow_none=True)
state = marshmallow.fields.String(required=False, allow_none=True)
description = marshmallow.fields.String(required=False, allow_none=True)
backtracks = marshmallow.fields.String(required=False, allow_none=True)
lane = marshmallow.fields.String(required=False, allow_none=True)
title = marshmallow.fields.String(required=False, allow_none=True)
task_id = marshmallow.fields.String(required=False, allow_none=True)
@marshmallow.post_load
def make_nav(self, data, **kwargs):
state = data.pop('state', None)
task_id = data.pop('task_id', None)
item = NavItem(**data)
item.state = state
item.task_id = task_id
return item
class WorkflowApi(object):
def __init__(self, id, status, next_task, navigation,

View File

@ -1,9 +1,8 @@
import copy
import json
import string
import uuid
from datetime import datetime
import random
import string
from datetime import datetime
from typing import List
import jinja2
@ -17,15 +16,14 @@ from SpiffWorkflow.bpmn.specs.UserTask import UserTask
from SpiffWorkflow.dmn.specs.BusinessRuleTask import BusinessRuleTask
from SpiffWorkflow.specs import CancelTask, StartTask
from SpiffWorkflow.util.deep_merge import DeepMerge
from flask import g
from jinja2 import Template
from crc import db, app
from crc.api.common import ApiError
from crc.models.api_models import Task, MultiInstanceType, NavigationItem, NavigationItemSchema, WorkflowApi
from crc.models.api_models import Task, MultiInstanceType, WorkflowApi
from crc.models.file import LookupDataModel
from crc.models.task_event import TaskEventModel
from crc.models.study import StudyModel
from crc.models.task_event import TaskEventModel
from crc.models.user import UserModel, UserModelSchema
from crc.models.workflow import WorkflowModel, WorkflowStatus, WorkflowSpecModel
from crc.services.file_service import FileService
@ -326,28 +324,20 @@ class WorkflowService(object):
# Some basic cleanup of the title for the for the navigation.
navigation = []
for nav_item in nav_dict:
spiff_task = processor.bpmn_workflow.get_task(nav_item['task_id'])
if 'description' in nav_item:
nav_item['title'] = nav_item.pop('description')
# fixme: duplicate code from the workflow_service. Should only do this in one place.
if nav_item['title'] is not None and ' ' in nav_item['title']:
nav_item['title'] = nav_item['title'].partition(' ')[2]
else:
nav_item['title'] = ""
spiff_task = processor.bpmn_workflow.get_task(nav_item.task_id)
if spiff_task:
nav_item['task'] = WorkflowService.spiff_task_to_api_task(spiff_task, add_docs_and_forms=False)
nav_item['title'] = nav_item['task'].title # Prefer the task title.
# Use existing logic to set the description, and alter the state based on permissions.
api_task = WorkflowService.spiff_task_to_api_task(spiff_task, add_docs_and_forms=False)
nav_item.description = api_task.title
user_uids = WorkflowService.get_users_assigned_to_task(processor, spiff_task)
if not UserService.in_list(user_uids, allow_admin_impersonate=True):
nav_item['state'] = WorkflowService.TASK_STATE_LOCKED
nav_item.state = WorkflowService.TASK_STATE_LOCKED
else:
nav_item['task'] = None
navigation.append(NavigationItem(**nav_item))
NavigationItemSchema().dump(nav_item)
# Strip off the first word in the description, to meet guidlines for BPMN.
if nav_item.description:
if nav_item.description is not None and ' ' in nav_item.description:
nav_item.description = nav_item.description.partition(' ')[2]
navigation.append(nav_item)
spec = db.session.query(WorkflowSpecModel).filter_by(id=processor.workflow_spec_id).first()
workflow_api = WorkflowApi(

View File

@ -1,11 +1,12 @@
<?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="4.2.0">
<bpmn:process id="Process_01143nb" name="PI&#39;s Pr" isExecutable="true">
<bpmn:process id="UserTask_ShowInvalidUIDs" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_0kcrx5l</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:scriptTask id="ScriptTask_LoadPersonnel" name="Load IRB Personnel">
<bpmn:incoming>Flow_0kcrx5l</bpmn:incoming>
<bpmn:incoming>Flow_00zanzw</bpmn:incoming>
<bpmn:outgoing>Flow_1dcsioh</bpmn:outgoing>
<bpmn:script>current_user = ldap()
investigators = study_info('investigators')
@ -15,11 +16,11 @@ is_cu_pi = False
if pi != None:
hasPI = True
if pi.get('uid', None) != None:
pi_has_uid = True
pi_invalid_uid = False
if pi['uid'] == current_user['uid']:
is_cu_pi = True
else:
pi_has_uid = False
pi_invalid_uid = True
else:
hasPI = False
@ -27,9 +28,11 @@ else:
dc = investigators.get('DEPT_CH', None)
if dc != None:
if dc.get('uid', None) != None:
dc_has_uid = True
dc_invalid_uid = False
else:
dc_has_uid = False
dc_invalid_uid = True
else:
dc_invalid_uid = False
# Primary Coordinators
pcs = {}
@ -39,13 +42,19 @@ for k in investigators.keys():
if k in ['SC_I','SC_II','IRBC']:
investigator = investigators.get(k)
if investigator.get('uid', None) != None:
cnt_pcs_uid = cnt_pcs_uid + 1
if investigator['uid'] != current_user['uid']:
pcs[k] = investigator
cnt_pcs_uid = cnt_pcs_uid + 1
else:
is_cu_pc = True
is_cu_pc_role = investigator['label']
else:
pcs[k] = investigator
cnt_pcs = len(pcs.keys())
if cnt_pcs != cnt_pcs_uid:
pcs_invalid_uid = True
else:
pcs_invalid_uid = False
if cnt_pcs &gt; 0:
del(k)
del(investigator)
@ -58,13 +67,19 @@ for k in investigators.keys():
if k == 'AS_C':
investigator = investigators.get(k)
if investigator.get('uid', None) != None:
cnt_acs_uid = cnt_acs_uid + 1
if investigator['uid'] != current_user['uid']:
acs[k] = investigator
cnt_acs_uid = cnt_acs_uid + 1
else:
is_cu_ac = True
is_cu_ac_role = investigator['label']
else:
acs[k] = investigator
cnt_acs = len(acs.keys())
if cnt_pcs != cnt_pcs_uid:
acs_invalid_uid = True
else:
acs_invalid_uid = False
if cnt_acs &gt; 0:
del(k)
del(investigator)
@ -77,12 +92,18 @@ for k in investigators.keys():
if k[:2] == 'SI':
investigator = investigators.get(k)
if investigator.get('uid', None) != None:
cnt_subs_uid = cnt_subs_uid + 1
if investigator['uid'] != current_user['uid']:
subs[k] = investigator
cnt_subs_uid = cnt_subs_uid + 1
else:
is_cu_subs = True
else:
subs[k] = investigator
cnt_subs = len(subs.keys())
if cnt_subs != cnt_subs_uid:
subs_invalid_uid = True
else:
subs_invalid_uid = False
if cnt_subs &gt; 0:
del(k)
del(investigator)
@ -95,13 +116,19 @@ for k in investigators.keys():
if k in ['SCI','DC']:
investigator = investigators.get(k)
if investigator.get('uid', None) != None:
cnt_aps_uid = cnt_aps_uid + 1
if investigator['uid'] != current_user['uid']:
aps[k] = investigator
cnt_aps_uid = cnt_aps_uid + 1
else:
is_cu_ap = True
is_cu_ap_role = investigator['label']
else:
aps[k] = investigator
cnt_aps = len(aps.keys())
if cnt_aps != cnt_aps_uid:
aps_invalid_uid = True
else:
aps_invalid_uid = False
if cnt_aps &gt; 0:
del(k)
del(investigator)
@ -132,12 +159,12 @@ Since you are the person entering this information, you already have access and
<camunda:property id="rows" value="5" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="pi.access" label="Should the Principal Investigator have full editing access in the system?" type="boolean" defaultValue="true">
<camunda:formField id="pi.access" label="Should the Principal Investigator have full editing access in the system?" type="boolean" defaultValue="True">
<camunda:properties>
<camunda:property id="hide_expression" value="is_cu_pi" />
</camunda:properties>
</camunda:formField>
<camunda:formField id="pi.emails" label="Should the Principal Investigator receive automated email notifications?" type="boolean" defaultValue="true">
<camunda:formField id="pi.emails" label="Should the Principal Investigator receive automated email notifications?" type="boolean" defaultValue="True">
<camunda:properties>
<camunda:property id="hide_expression" value="is_cu_pi" />
</camunda:properties>
@ -160,23 +187,23 @@ Since you are the person entering this information, you already have access and
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_0kcrx5l" sourceRef="StartEvent_1" targetRef="ScriptTask_LoadPersonnel" />
<bpmn:sequenceFlow id="Flow_1dcsioh" sourceRef="ScriptTask_LoadPersonnel" targetRef="Gateway_CheckForPI" />
<bpmn:exclusiveGateway id="Gateway_CheckForPI" name="PI Cnt" default="Flow_147b9li">
<bpmn:exclusiveGateway id="Gateway_CheckForPI" name="PI With Valid UID?" default="Flow_147b9li">
<bpmn:incoming>Flow_1dcsioh</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="ScriptTask_DeterminePI_E0_Department" />
<bpmn:sequenceFlow id="Flow_00prawo" name="No PI from PB" sourceRef="Gateway_CheckForPI" targetRef="Activity_1qwzwyi">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">not(hasPI) or (hasPI and not(pi_has_uid))</bpmn:conditionExpression>
<bpmn:sequenceFlow id="Flow_147b9li" name="Yes" sourceRef="Gateway_CheckForPI" targetRef="Gateway_CheckUIDs" />
<bpmn:sequenceFlow id="Flow_00prawo" name="No" sourceRef="Gateway_CheckForPI" targetRef="Activity_1qwzwyi">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">not(hasPI) or (hasPI and pi_invalid_uid)</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:manualTask id="Activity_1qwzwyi" name="Show No PI">
<bpmn:manualTask id="Activity_1qwzwyi" name="Show No PI or Invalid UID">
<bpmn:documentation>No PI entered in PB</bpmn:documentation>
<bpmn:incoming>Flow_00prawo</bpmn:incoming>
<bpmn:outgoing>Flow_16qr5jf</bpmn:outgoing>
</bpmn:manualTask>
<bpmn:exclusiveGateway id="Gateway_0jykh6r" name="How many Primary Coordinators?" default="Flow_0xifvai">
<bpmn:incoming>Flow_0kpe12r</bpmn:incoming>
<bpmn:incoming>SequenceFlow_0cdtt11</bpmn:incoming>
<bpmn:incoming>Flow_1ayisx2</bpmn:incoming>
<bpmn:outgoing>Flow_0xifvai</bpmn:outgoing>
<bpmn:outgoing>Flow_1oqem42</bpmn:outgoing>
</bpmn:exclusiveGateway>
@ -210,7 +237,8 @@ Otherwise, edit each Coordinator as necessary and select the Save button for eac
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">cnt_pcs == 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:scriptTask id="ScriptTask_DeterminePI_E0_Department" name="Determine PI E0 Department">
<bpmn:incoming>Flow_147b9li</bpmn:incoming>
<bpmn:incoming>Flow_0tfprc8</bpmn:incoming>
<bpmn:incoming>Flow_0tsdclr</bpmn:incoming>
<bpmn:outgoing>Flow_1grahhv</bpmn:outgoing>
<bpmn:script>LDAP_dept = pi.department
length_LDAP_dept = len(LDAP_dept)
@ -274,36 +302,12 @@ else:
<bpmn:incoming>Flow_0w4d2bz</bpmn:incoming>
<bpmn:outgoing>Flow_1oo0ijr</bpmn:outgoing>
</bpmn:businessRuleTask>
<bpmn:userTask id="UserTask_109otvi" name="Update Chair Info" camunda:formKey="RO_Chair_Info">
<bpmn:documentation>***Name &amp; Degree:*** {{ RO_Chair_Name_Degree }}
***School:*** {{ RO_School }}
***Department:*** {{ RO_Department }}
***Title:*** {{ RO_Chair_Title }}
***Email:*** {{ RO_Chair_CID }}
{% if RO_Chair_CID != dc.uid %}
*Does not match the Department Chair specified in Protocol Builder, {{ dc.display_name }}*
{% endif %}</bpmn:documentation>
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="RO_ChairAccess" label="Should the Department Chair have full editing access in the system?" type="boolean" defaultValue="false" />
<camunda:formField id="RO_ChairEmails" label="Should the Department Chair receive automated email notifications?" type="boolean" defaultValue="false" />
</camunda:formData>
<camunda:properties>
<camunda:property name="display_name" value="&#34;Responsible Organization&#39;s Chair Info&#34;" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0vi6thu</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_0cdtt11</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="SequenceFlow_0cdtt11" sourceRef="UserTask_109otvi" targetRef="Gateway_0jykh6r" />
<bpmn:exclusiveGateway id="Gateway_PI_is_DeptChair" name="PI is Dept Chair?" default="Flow_0vi6thu">
<bpmn:incoming>Flow_070j5fg</bpmn:incoming>
<bpmn:outgoing>Flow_0vi6thu</bpmn:outgoing>
<bpmn:outgoing>Flow_00yhlrq</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0vi6thu" name="No" sourceRef="Gateway_PI_is_DeptChair" targetRef="UserTask_109otvi" />
<bpmn:sequenceFlow id="Flow_0vi6thu" name="No" sourceRef="Gateway_PI_is_DeptChair" targetRef="Activity_1sffono" />
<bpmn:sequenceFlow id="Flow_00yhlrq" name="Yes" sourceRef="Gateway_PI_is_DeptChair" targetRef="Activity_ShowPI_is_DeptChair">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">RO_Chair_CID == pi.uid</bpmn:conditionExpression>
</bpmn:sequenceFlow>
@ -360,6 +364,7 @@ Otherwise, edit each Sub-Investigator as necessary and select the Save button fo
<bpmn:outgoing>Flow_1kg5jot</bpmn:outgoing>
<bpmn:script>pi.E0.schoolName = PI_E0_schoolName
pi.E0.deptName = PI_E0_deptName
pi.experience = user_data_get("pi_experience","")
ro = {}
ro['chair'] = {}</bpmn:script>
</bpmn:scriptTask>
@ -605,17 +610,17 @@ ro.schoolAbbrv = RO_StudySchool.value</bpmn:script>
<bpmn:outgoing>Flow_0vff9k5</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0vff9k5" sourceRef="Gateway_0zd7syo" targetRef="BusinessRuleTask_Determine_RO_Chair" />
<bpmn:exclusiveGateway id="Gateway_13k761k" name="How many Additional Personnel? " default="Flow_0kp47dz">
<bpmn:exclusiveGateway id="Gateway_13k761k" name="How many Additional Personnel? " default="Flow_0q56tn8">
<bpmn:incoming>Flow_0ofpgml</bpmn:incoming>
<bpmn:incoming>Flow_0jxzqw1</bpmn:incoming>
<bpmn:outgoing>Flow_0q56tn8</bpmn:outgoing>
<bpmn:outgoing>Flow_0kp47dz</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0q56tn8" sourceRef="Gateway_13k761k" targetRef="Activity_1sra1vn">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">cnt_aps &gt; 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_0q56tn8" sourceRef="Gateway_13k761k" targetRef="Activity_1sra1vn" />
<bpmn:sequenceFlow id="Flow_10zn0h1" sourceRef="Activity_1sra1vn" targetRef="EndEvent_1qor16n" />
<bpmn:sequenceFlow id="Flow_0kp47dz" sourceRef="Gateway_13k761k" targetRef="EndEvent_1qor16n" />
<bpmn:sequenceFlow id="Flow_0kp47dz" sourceRef="Gateway_13k761k" targetRef="EndEvent_1qor16n">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">cnt_aps == 0</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:userTask id="Activity_1sra1vn" name="Update Additional Personnel Info" camunda:formKey="AP_AccessEmails">
<bpmn:documentation>The following Additional Personnel were entered in Protocol Builder:
{%+ for key, value in aps.items() %}{{value.display_name}} ({{key}}){% if loop.index is lt cnt_aps %}, {% endif %}{% endfor %}
@ -646,400 +651,545 @@ Otherwise, edit each Additional Personnel as necessary and select the Save butto
<bpmn:outgoing>Flow_10zn0h1</bpmn:outgoing>
<bpmn:multiInstanceLoopCharacteristics camunda:collection="aps" camunda:elementVariable="ap" />
</bpmn:userTask>
<bpmn:exclusiveGateway id="Gateway_CheckUIDs" name="Invalid UIDs?" default="Flow_0tfprc8">
<bpmn:incoming>Flow_147b9li</bpmn:incoming>
<bpmn:outgoing>Flow_0tfprc8</bpmn:outgoing>
<bpmn:outgoing>Flow_0nz62mu</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_0tfprc8" name="No" sourceRef="Gateway_CheckUIDs" targetRef="ScriptTask_DeterminePI_E0_Department" />
<bpmn:sequenceFlow id="Flow_0nz62mu" name="Yes" sourceRef="Gateway_CheckUIDs" targetRef="Activity_19z6vct">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">dc_invalid_uid or pcs_invalid_uid or acs_invalid_uid or subs_invalid_uid or aps_invalid_uid</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:userTask id="Activity_19z6vct" name="Show Invalid UIDs" camunda:formKey="ShowInvalidUIDs">
<bpmn:documentation>Select No if all displayed invalid Computing IDs do not need system access and/or receive emails. If they do, correct in Protocol Builder first and then select Yes.
{% if dc_invalid_uid %}
Department Chair
{{ dc.error }}
{% endif %}
{% if pcs_invalid_uid %}
Primary Coordinators
{% for k, pc in pcs.items() %}
{% if pc.get('uid', None) == None: %}
{{ pc.error }}
{% endif %}
{% endfor %}
{% endif %}
{% if acs_invalid_uid %}
Additional Coordinators
{% for k, ac in acs.items() %}
{% if ac.get('uid', None) == None: %}
{{ ac.error }}
{% endif %}
{% endfor %}
{% endif %}
{% if subs_invalid_uid %}
Sub-Investigators
{% for k, sub in subs.items() %}
{% if sub.get('uid', None) == None: %}
{{ sub.error }}
{% endif %}
{% endfor %}
{% endif %}
{% if aps_invalid_uid %}
Additional Personnnel
{% for k, ap in aps.items() %}
{% if ap.get('uid', None) == None: %}
{{ ap.error }}
{% endif %}
{% endfor %}
{% endif %}</bpmn:documentation>
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="FixInvalidUIDs" label="Do you want to fix?" type="boolean">
<camunda:properties>
<camunda:property id="description" value="Select Yes if you have corrected in Protocol Builder, No if you would like to proceed without correcting." />
</camunda:properties>
</camunda:formField>
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0nz62mu</bpmn:incoming>
<bpmn:outgoing>Flow_16bkbuc</bpmn:outgoing>
</bpmn:userTask>
<bpmn:exclusiveGateway id="Gateway_FixInvalidUIDs" name="Fix Invalid UIDs?" default="Flow_00zanzw">
<bpmn:incoming>Flow_16bkbuc</bpmn:incoming>
<bpmn:outgoing>Flow_00zanzw</bpmn:outgoing>
<bpmn:outgoing>Flow_0tsdclr</bpmn:outgoing>
</bpmn:exclusiveGateway>
<bpmn:sequenceFlow id="Flow_16bkbuc" sourceRef="Activity_19z6vct" targetRef="Gateway_FixInvalidUIDs" />
<bpmn:sequenceFlow id="Flow_00zanzw" name="Yes" sourceRef="Gateway_FixInvalidUIDs" targetRef="ScriptTask_LoadPersonnel" />
<bpmn:sequenceFlow id="Flow_0tsdclr" name="No" sourceRef="Gateway_FixInvalidUIDs" targetRef="ScriptTask_DeterminePI_E0_Department">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">not(FixInvalidUIDs)</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:userTask id="Activity_1sffono" name="Update Chair Info" camunda:formKey="RO_Chair_Info">
<bpmn:documentation>***Name &amp; Degree:*** {{ RO_Chair_Name_Degree }}
***School:*** {{ RO_School }}
***Department:*** {{ RO_Department }}
***Title:*** {{ RO_Chair_Title }}
***Email:*** {{ RO_Chair_CID }}
{% if RO_Chair_CID != dc.uid %}
*Does not match the Department Chair specified in Protocol Builder, {{ dc.display_name }}*
{% endif %}</bpmn:documentation>
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="RO_ChairAccess" label="Should the Department Chair have full editing access in the system?" type="boolean" defaultValue="false" />
<camunda:formField id="RO_ChairEmails" label="Should the Department Chair receive automated email notifications?" type="boolean" defaultValue="false" />
</camunda:formData>
<camunda:properties>
<camunda:property name="display_name" value="&#34;Responsible Organization&#39;s Chair Info&#34;" />
</camunda:properties>
</bpmn:extensionElements>
<bpmn:incoming>Flow_0vi6thu</bpmn:incoming>
<bpmn:outgoing>Flow_1ayisx2</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1ayisx2" sourceRef="Activity_1sffono" targetRef="Gateway_0jykh6r" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_01143nb">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="UserTask_ShowInvalidUIDs">
<bpmndi:BPMNEdge id="Flow_1ayisx2_di" bpmnElement="Flow_1ayisx2">
<di:waypoint x="2810" y="290" />
<di:waypoint x="2875" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tsdclr_di" bpmnElement="Flow_0tsdclr">
<di:waypoint x="715" y="540" />
<di:waypoint x="860" y="540" />
<di:waypoint x="860" y="330" />
<bpmndi:BPMNLabel>
<dc:Bounds x="781" y="522" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00zanzw_di" bpmnElement="Flow_00zanzw">
<di:waypoint x="690" y="565" />
<di:waypoint x="690" y="610" />
<di:waypoint x="360" y="610" />
<di:waypoint x="360" y="330" />
<bpmndi:BPMNLabel>
<dc:Bounds x="516" y="592" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_16bkbuc_di" bpmnElement="Flow_16bkbuc">
<di:waypoint x="690" y="460" />
<di:waypoint x="690" y="515" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0nz62mu_di" bpmnElement="Flow_0nz62mu">
<di:waypoint x="690" y="315" />
<di:waypoint x="690" y="380" />
<bpmndi:BPMNLabel>
<dc:Bounds x="696" y="345" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0tfprc8_di" bpmnElement="Flow_0tfprc8">
<di:waypoint x="715" y="290" />
<di:waypoint x="810" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="756" y="272" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0kp47dz_di" bpmnElement="Flow_0kp47dz">
<di:waypoint x="3800" y="265" />
<di:waypoint x="3800" y="200" />
<di:waypoint x="4150" y="200" />
<di:waypoint x="4150" y="272" />
<di:waypoint x="3960" y="265" />
<di:waypoint x="3960" y="200" />
<di:waypoint x="4310" y="200" />
<di:waypoint x="4310" y="272" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_10zn0h1_di" bpmnElement="Flow_10zn0h1">
<di:waypoint x="4030" y="290" />
<di:waypoint x="4132" y="290" />
<di:waypoint x="4190" y="290" />
<di:waypoint x="4292" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0q56tn8_di" bpmnElement="Flow_0q56tn8">
<di:waypoint x="3825" y="290" />
<di:waypoint x="3930" y="290" />
<di:waypoint x="3985" y="290" />
<di:waypoint x="4090" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0vff9k5_di" bpmnElement="Flow_0vff9k5">
<di:waypoint x="2040" y="375" />
<di:waypoint x="2040" y="330" />
<di:waypoint x="2200" y="375" />
<di:waypoint x="2200" y="330" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0iuzu7j_di" bpmnElement="Flow_0iuzu7j">
<di:waypoint x="2015" y="830" />
<di:waypoint x="1900" y="830" />
<di:waypoint x="1900" y="760" />
<di:waypoint x="2175" y="830" />
<di:waypoint x="2060" y="830" />
<di:waypoint x="2060" y="760" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1905" y="783" width="49" height="14" />
<dc:Bounds x="2065" y="783" width="49" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0giqf35_di" bpmnElement="Flow_0giqf35">
<di:waypoint x="2065" y="830" />
<di:waypoint x="2180" y="830" />
<di:waypoint x="2180" y="760" />
<di:waypoint x="2225" y="830" />
<di:waypoint x="2340" y="830" />
<di:waypoint x="2340" y="760" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2189" y="783" width="22" height="14" />
<dc:Bounds x="2349" y="783" width="22" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0mdjaid_di" bpmnElement="Flow_0mdjaid">
<di:waypoint x="2040" y="900" />
<di:waypoint x="2040" y="855" />
<di:waypoint x="2200" y="900" />
<di:waypoint x="2200" y="855" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1vyg8ir_di" bpmnElement="Flow_1vyg8ir">
<di:waypoint x="2180" y="680" />
<di:waypoint x="2180" y="620" />
<di:waypoint x="2065" y="620" />
<di:waypoint x="2340" y="680" />
<di:waypoint x="2340" y="620" />
<di:waypoint x="2225" y="620" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0zc01f9_di" bpmnElement="Flow_0zc01f9">
<di:waypoint x="2040" y="680" />
<di:waypoint x="2040" y="645" />
<di:waypoint x="2200" y="680" />
<di:waypoint x="2200" y="645" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1vv63qa_di" bpmnElement="Flow_1vv63qa">
<di:waypoint x="2040" y="460" />
<di:waypoint x="2040" y="425" />
<di:waypoint x="2200" y="460" />
<di:waypoint x="2200" y="425" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1azfvtx_di" bpmnElement="Flow_1azfvtx">
<di:waypoint x="2040" y="805" />
<di:waypoint x="2040" y="760" />
<di:waypoint x="2200" y="805" />
<di:waypoint x="2200" y="760" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2047" y="783" width="45" height="14" />
<dc:Bounds x="2207" y="783" width="45" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0w4d2bz_di" bpmnElement="Flow_0w4d2bz">
<di:waypoint x="1775" y="290" />
<di:waypoint x="1990" y="290" />
<di:waypoint x="1935" y="290" />
<di:waypoint x="2150" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1mplloa_di" bpmnElement="Flow_1mplloa">
<di:waypoint x="1460" y="290" />
<di:waypoint x="1540" y="290" />
<di:waypoint x="1620" y="290" />
<di:waypoint x="1700" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1va8c15_di" bpmnElement="Flow_1va8c15">
<di:waypoint x="1640" y="290" />
<di:waypoint x="1725" y="290" />
<di:waypoint x="1800" y="290" />
<di:waypoint x="1885" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0m9peiz_di" bpmnElement="Flow_0m9peiz">
<di:waypoint x="2040" y="595" />
<di:waypoint x="2040" y="540" />
<di:waypoint x="2200" y="595" />
<di:waypoint x="2200" y="540" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0fw4rck_di" bpmnElement="Flow_0fw4rck">
<di:waypoint x="2065" y="830" />
<di:waypoint x="2270" y="830" />
<di:waypoint x="2270" y="400" />
<di:waypoint x="2065" y="400" />
<di:waypoint x="2225" y="830" />
<di:waypoint x="2430" y="830" />
<di:waypoint x="2430" y="400" />
<di:waypoint x="2225" y="400" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2278" y="603" width="15" height="14" />
<dc:Bounds x="2438" y="603" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0whqr3p_di" bpmnElement="Flow_0whqr3p">
<di:waypoint x="1900" y="680" />
<di:waypoint x="1900" y="620" />
<di:waypoint x="2015" y="620" />
<di:waypoint x="2060" y="680" />
<di:waypoint x="2060" y="620" />
<di:waypoint x="2175" y="620" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yz8k2a_di" bpmnElement="Flow_1yz8k2a">
<di:waypoint x="2040" y="1050" />
<di:waypoint x="2040" y="980" />
<di:waypoint x="2200" y="1050" />
<di:waypoint x="2200" y="980" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1fj9iz0_di" bpmnElement="Flow_1fj9iz0">
<di:waypoint x="1800" y="1090" />
<di:waypoint x="1990" y="1090" />
<di:waypoint x="1960" y="1090" />
<di:waypoint x="2150" y="1090" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ycdxbl_di" bpmnElement="Flow_0ycdxbl">
<di:waypoint x="1750" y="855" />
<di:waypoint x="1750" y="1050" />
<di:waypoint x="1910" y="855" />
<di:waypoint x="1910" y="1050" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1722" y="933" width="15" height="14" />
<dc:Bounds x="1882" y="933" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_13la8l3_di" bpmnElement="Flow_13la8l3">
<di:waypoint x="1775" y="830" />
<di:waypoint x="2015" y="830" />
<di:waypoint x="1935" y="830" />
<di:waypoint x="2175" y="830" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1811" y="813" width="18" height="14" />
<dc:Bounds x="1971" y="813" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yd7kbi_di" bpmnElement="Flow_1yd7kbi">
<di:waypoint x="1750" y="315" />
<di:waypoint x="1750" y="805" />
<di:waypoint x="1910" y="315" />
<di:waypoint x="1910" y="805" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1722" y="691" width="15" height="14" />
<dc:Bounds x="1882" y="691" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0dt3pjw_di" bpmnElement="Flow_0dt3pjw">
<di:waypoint x="3100" y="265" />
<di:waypoint x="3100" y="180" />
<di:waypoint x="3480" y="180" />
<di:waypoint x="3480" y="265" />
<di:waypoint x="3260" y="265" />
<di:waypoint x="3260" y="180" />
<di:waypoint x="3640" y="180" />
<di:waypoint x="3640" y="265" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3277" y="162" width="27" height="14" />
<dc:Bounds x="3437" y="162" width="27" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_12ss6u8_di" bpmnElement="Flow_12ss6u8">
<di:waypoint x="3340" y="290" />
<di:waypoint x="3455" y="290" />
<di:waypoint x="3500" y="290" />
<di:waypoint x="3615" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1gtl2o3_di" bpmnElement="Flow_1gtl2o3">
<di:waypoint x="3125" y="290" />
<di:waypoint x="3240" y="290" />
<di:waypoint x="3285" y="290" />
<di:waypoint x="3400" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3159" y="272" width="48" height="14" />
<dc:Bounds x="3319" y="272" width="48" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_070j5fg_di" bpmnElement="Flow_070j5fg">
<di:waypoint x="2270" y="290" />
<di:waypoint x="2365" y="290" />
<di:waypoint x="2430" y="290" />
<di:waypoint x="2525" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1kg5jot_di" bpmnElement="Flow_1kg5jot">
<di:waypoint x="1280" y="290" />
<di:waypoint x="1360" y="290" />
<di:waypoint x="1440" y="290" />
<di:waypoint x="1520" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_16qr5jf_di" bpmnElement="Flow_16qr5jf">
<di:waypoint x="580" y="410" />
<di:waypoint x="642" y="410" />
<di:waypoint x="740" y="150" />
<di:waypoint x="822" y="150" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0jxzqw1_di" bpmnElement="Flow_0jxzqw1">
<di:waypoint x="3480" y="315" />
<di:waypoint x="3480" y="390" />
<di:waypoint x="3800" y="390" />
<di:waypoint x="3800" y="315" />
<di:waypoint x="3640" y="315" />
<di:waypoint x="3640" y="390" />
<di:waypoint x="3960" y="390" />
<di:waypoint x="3960" y="315" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3627" y="372" width="27" height="14" />
<dc:Bounds x="3787" y="372" width="27" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0ofpgml_di" bpmnElement="Flow_0ofpgml">
<di:waypoint x="3710" y="290" />
<di:waypoint x="3775" y="290" />
<di:waypoint x="3870" y="290" />
<di:waypoint x="3935" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_05rqrlf_di" bpmnElement="Flow_05rqrlf">
<di:waypoint x="3505" y="290" />
<di:waypoint x="3610" y="290" />
<di:waypoint x="3665" y="290" />
<di:waypoint x="3770" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3534" y="272" width="48" height="14" />
<dc:Bounds x="3694" y="272" width="48" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0kpe12r_di" bpmnElement="Flow_0kpe12r">
<di:waypoint x="2440" y="120" />
<di:waypoint x="2740" y="120" />
<di:waypoint x="2740" y="260" />
<di:waypoint x="2600" y="120" />
<di:waypoint x="2900" y="120" />
<di:waypoint x="2900" y="260" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00yhlrq_di" bpmnElement="Flow_00yhlrq">
<di:waypoint x="2390" y="265" />
<di:waypoint x="2390" y="160" />
<di:waypoint x="2550" y="265" />
<di:waypoint x="2550" y="160" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2401" y="178" width="18" height="14" />
<dc:Bounds x="2561" y="178" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0vi6thu_di" bpmnElement="Flow_0vi6thu">
<di:waypoint x="2415" y="290" />
<di:waypoint x="2540" y="290" />
<di:waypoint x="2575" y="290" />
<di:waypoint x="2710" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2471" y="272" width="15" height="14" />
<dc:Bounds x="2620" y="272" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_0cdtt11_di" bpmnElement="SequenceFlow_0cdtt11">
<di:waypoint x="2640" y="290" />
<di:waypoint x="2715" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1oo0ijr_di" bpmnElement="Flow_1oo0ijr">
<di:waypoint x="2090" y="290" />
<di:waypoint x="2170" y="290" />
<di:waypoint x="2250" y="290" />
<di:waypoint x="2330" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1eaikyp_di" bpmnElement="Flow_1eaikyp">
<di:waypoint x="920" y="290" />
<di:waypoint x="1010" y="290" />
<di:waypoint x="1070" y="290" />
<di:waypoint x="1160" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1wz38hl_di" bpmnElement="Flow_1wz38hl">
<di:waypoint x="1110" y="290" />
<di:waypoint x="1180" y="290" />
<di:waypoint x="1260" y="290" />
<di:waypoint x="1340" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1grahhv_di" bpmnElement="Flow_1grahhv">
<di:waypoint x="750" y="290" />
<di:waypoint x="820" y="290" />
<di:waypoint x="910" y="290" />
<di:waypoint x="970" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1oqem42_di" bpmnElement="Flow_1oqem42">
<di:waypoint x="2740" y="315" />
<di:waypoint x="2740" y="400" />
<di:waypoint x="3100" y="400" />
<di:waypoint x="3100" y="315" />
<di:waypoint x="2900" y="315" />
<di:waypoint x="2900" y="400" />
<di:waypoint x="3260" y="400" />
<di:waypoint x="3260" y="315" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2916" y="383" width="27" height="14" />
<dc:Bounds x="3076" y="383" width="27" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1n0k4pd_di" bpmnElement="Flow_1n0k4pd">
<di:waypoint x="2980" y="290" />
<di:waypoint x="3075" y="290" />
<di:waypoint x="3140" y="290" />
<di:waypoint x="3235" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0xifvai_di" bpmnElement="Flow_0xifvai">
<di:waypoint x="2765" y="290" />
<di:waypoint x="2880" y="290" />
<di:waypoint x="2925" y="290" />
<di:waypoint x="3040" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2793" y="273" width="48" height="14" />
<dc:Bounds x="2953" y="273" width="48" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_00prawo_di" bpmnElement="Flow_00prawo">
<di:waypoint x="350" y="315" />
<di:waypoint x="350" y="410" />
<di:waypoint x="480" y="410" />
<di:waypoint x="510" y="265" />
<di:waypoint x="510" y="150" />
<di:waypoint x="640" y="150" />
<bpmndi:BPMNLabel>
<dc:Bounds x="359" y="353" width="71" height="14" />
<dc:Bounds x="483" y="204" width="15" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_147b9li_di" bpmnElement="Flow_147b9li">
<di:waypoint x="375" y="290" />
<di:waypoint x="650" y="290" />
<di:waypoint x="535" y="290" />
<di:waypoint x="665" y="290" />
<bpmndi:BPMNLabel>
<dc:Bounds x="402" y="273" width="63" height="14" />
<dc:Bounds x="583" y="273" width="18" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1dcsioh_di" bpmnElement="Flow_1dcsioh">
<di:waypoint x="250" y="290" />
<di:waypoint x="325" y="290" />
<di:waypoint x="410" y="290" />
<di:waypoint x="485" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0kcrx5l_di" bpmnElement="Flow_0kcrx5l">
<di:waypoint x="28" y="290" />
<di:waypoint x="150" y="290" />
<di:waypoint x="188" y="290" />
<di:waypoint x="310" y="290" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="-8" y="272" width="36" height="36" />
<dc:Bounds x="152" y="272" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ScriptTask_0h49cmf_di" bpmnElement="ScriptTask_LoadPersonnel">
<dc:Bounds x="150" y="250" width="100" height="80" />
<dc:Bounds x="310" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_1qor16n_di" bpmnElement="EndEvent_1qor16n">
<dc:Bounds x="4132" y="272" width="36" height="36" />
<dc:Bounds x="4292" y="272" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="4140" y="318" width="20" height="14" />
<dc:Bounds x="4300" y="318" width="20" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0d622qi_di" bpmnElement="Activity_EditPI">
<dc:Bounds x="1360" y="250" width="100" height="80" />
<dc:Bounds x="1520" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0qzf1r3_di" bpmnElement="Gateway_CheckForPI" isMarkerVisible="true">
<dc:Bounds x="325" y="265" width="50" height="50" />
<dc:Bounds x="485" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="334" y="241" width="31" height="14" />
<dc:Bounds x="478" y="325" width="63" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0neg931_di" bpmnElement="Activity_1qwzwyi">
<dc:Bounds x="480" y="370" width="100" height="80" />
<dc:Bounds x="640" y="110" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0jykh6r_di" bpmnElement="Gateway_0jykh6r" isMarkerVisible="true">
<dc:Bounds x="2715" y="265" width="50" height="50" />
<dc:Bounds x="2875" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2745" y="309" width="70" height="40" />
<dc:Bounds x="2905" y="309" width="70" height="40" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1nz85vv_di" bpmnElement="TaskPMI_UpdateCoordinatorInfo">
<dc:Bounds x="2880" y="250" width="100" height="80" />
<dc:Bounds x="3040" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1z05bvn_di" bpmnElement="ScriptTask_DeterminePI_E0_Department">
<dc:Bounds x="650" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0uz6yhu_di" bpmnElement="BusinessRule_PI_Dept">
<dc:Bounds x="1010" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1sn7wxh_di" bpmnElement="BusinessRule_PI_School">
<dc:Bounds x="820" y="250" width="100" height="80" />
<dc:Bounds x="810" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_1a7hck9_di" bpmnElement="UserTask_SelectChair">
<dc:Bounds x="1850" y="680" width="100" height="80" />
<dc:Bounds x="2010" y="680" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1sk9596_di" bpmnElement="BusinessRuleTask_Determine_RO_Chair">
<dc:Bounds x="1990" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="UserTask_109otvi_di" bpmnElement="UserTask_109otvi">
<dc:Bounds x="2540" y="250" width="100" height="80" />
<dc:Bounds x="2150" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1xio5hy_di" bpmnElement="Gateway_PI_is_DeptChair" isMarkerVisible="true">
<dc:Bounds x="2365" y="265" width="50" height="50" />
<dc:Bounds x="2525" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2348" y="322" width="84" height="14" />
<dc:Bounds x="2508" y="322" width="84" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0i869dj_di" bpmnElement="Activity_ShowPI_is_DeptChair">
<dc:Bounds x="2340" y="80" width="100" height="80" />
<dc:Bounds x="2500" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1oxt6h1_di" bpmnElement="Gateway_1oxt6h1" isMarkerVisible="true">
<dc:Bounds x="3455" y="265" width="50" height="50" />
<dc:Bounds x="3615" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3500" y="315" width="79" height="27" />
<dc:Bounds x="3660" y="315" width="79" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0oyqfs3_di" bpmnElement="Activity_0yd4wuz">
<dc:Bounds x="3610" y="250" width="100" height="80" />
<dc:Bounds x="3770" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0npjf2p_di" bpmnElement="Event_0npjf2p">
<dc:Bounds x="642" y="392" width="36" height="36" />
<dc:Bounds x="822" y="132" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_02led02_di" bpmnElement="ScriptTask_Update_PIData">
<dc:Bounds x="1180" y="250" width="100" height="80" />
<dc:Bounds x="1340" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1mt9o4o_di" bpmnElement="ScriptTask_UpdateRO_Data">
<dc:Bounds x="2170" y="250" width="100" height="80" />
<dc:Bounds x="2330" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0zrcknh_di" bpmnElement="Gateway_0zrcknh" isMarkerVisible="true">
<dc:Bounds x="3075" y="265" width="50" height="50" />
<dc:Bounds x="3235" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3115" y="309" width="70" height="40" />
<dc:Bounds x="3275" y="309" width="70" height="40" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1gqvpu9_di" bpmnElement="Activity_1yjg742">
<dc:Bounds x="3240" y="250" width="100" height="80" />
<dc:Bounds x="3400" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_10ngpfu_di" bpmnElement="Gateway_10ngpfu" isMarkerVisible="true">
<dc:Bounds x="1725" y="265" width="50" height="50" />
<dc:Bounds x="1885" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1706" y="170" width="88" height="80" />
<dc:Bounds x="1866" y="170" width="88" height="80" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_141zszd_di" bpmnElement="Gateway_141zszd" isMarkerVisible="true">
<dc:Bounds x="1725" y="805" width="50" height="50" />
<dc:Bounds x="1885" y="805" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="1644" y="823" width="72" height="14" />
<dc:Bounds x="1804" y="823" width="72" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0vjz7wg_di" bpmnElement="Activity_1h5mjwh">
<dc:Bounds x="1700" y="1050" width="100" height="80" />
<dc:Bounds x="1860" y="1050" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0evmxd3_di" bpmnElement="Activity_141w33n">
<dc:Bounds x="1990" y="1050" width="100" height="80" />
<dc:Bounds x="2150" y="1050" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1dfciuq_di" bpmnElement="Gateway_1dfciuq" isMarkerVisible="true">
<dc:Bounds x="2015" y="805" width="50" height="50" />
<dc:Bounds x="2175" y="805" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="2055" y="846" width="70" height="27" />
<dc:Bounds x="2215" y="846" width="70" height="27" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1gzewp9_di" bpmnElement="Gateway_1gzewp9" isMarkerVisible="true">
<dc:Bounds x="2015" y="595" width="50" height="50" />
<dc:Bounds x="2175" y="595" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0zjabzm_di" bpmnElement="BusinessRuleTask_Determine_RO">
<dc:Bounds x="1990" y="460" width="100" height="80" />
<dc:Bounds x="2150" y="460" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_11muu5l_di" bpmnElement="Activity_11muu5l">
<dc:Bounds x="1990" y="680" width="100" height="80" />
<dc:Bounds x="2150" y="680" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_18f2rpz_di" bpmnElement="ScriptTask_SetRO_SchoolAndDept">
<dc:Bounds x="1700" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1bvro77_di" bpmnElement="Activity_1bvro77">
<dc:Bounds x="2130" y="680" width="100" height="80" />
<dc:Bounds x="2290" y="680" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1yen2d0_di" bpmnElement="Activity_1yen2d0">
<dc:Bounds x="1990" y="900" width="100" height="80" />
<dc:Bounds x="2150" y="900" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0zd7syo_di" bpmnElement="Gateway_0zd7syo" isMarkerVisible="true">
<dc:Bounds x="2015" y="375" width="50" height="50" />
<dc:Bounds x="2175" y="375" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_13k761k_di" bpmnElement="Gateway_13k761k" isMarkerVisible="true">
<dc:Bounds x="3775" y="265" width="50" height="50" />
<dc:Bounds x="3935" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="3822" y="309" width="56" height="40" />
<dc:Bounds x="3982" y="309" width="56" height="40" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1m6r78y_di" bpmnElement="Activity_1sra1vn">
<dc:Bounds x="3930" y="250" width="100" height="80" />
<dc:Bounds x="4090" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_18f2rpz_di" bpmnElement="ScriptTask_SetRO_SchoolAndDept">
<dc:Bounds x="1540" y="250" width="100" height="80" />
<bpmndi:BPMNShape id="Gateway_1gq2m4q_di" bpmnElement="Gateway_CheckUIDs" isMarkerVisible="true">
<dc:Bounds x="665" y="265" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="657" y="241" width="66" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1l5u9mj_di" bpmnElement="Activity_19z6vct">
<dc:Bounds x="640" y="380" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_01e55pl_di" bpmnElement="Gateway_FixInvalidUIDs" isMarkerVisible="true">
<dc:Bounds x="665" y="515" width="50" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="570" y="530" width="84" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1sffono_di" bpmnElement="Activity_1sffono">
<dc:Bounds x="2710" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1sn7wxh_di" bpmnElement="BusinessRule_PI_School">
<dc:Bounds x="970" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0uz6yhu_di" bpmnElement="BusinessRule_PI_Dept">
<dc:Bounds x="1160" y="250" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>

View File

@ -68,7 +68,7 @@ class TestTasksApi(BaseTest):
# get the first form in the two form workflow.
workflow_api = self.get_workflow_api(workflow)
self.assertEqual('two_forms', workflow_api.workflow_spec_id)
self.assertEqual(2, len(workflow_api.navigation))
self.assertEqual(4, len(workflow_api.navigation))
self.assertIsNotNone(workflow_api.next_task.form)
self.assertEqual("UserTask", workflow_api.next_task.type)
self.assertEqual("StepOne", workflow_api.next_task.name)
@ -113,14 +113,19 @@ class TestTasksApi(BaseTest):
self.assertIsNotNone(workflow_api.navigation)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual("Do You Have Bananas", nav[0]['title'])
self.assertEqual("Bananas?", nav[1]['title'])
self.assertEqual("FUTURE", nav[1]['state'])
self.assertEqual("yes", nav[2]['title'])
self.assertEqual("NOOP", nav[2]['state'])
self.assertEqual("no", nav[3]['title'])
self.assertEqual("NOOP", nav[3]['state'])
self.assertEqual(9, len(nav))
self.assertEqual("Do You Have Bananas", nav[1].description)
self.assertEqual("Bananas?", nav[2].description)
self.assertEqual("FUTURE", nav[2].state)
self.assertEqual("yes", nav[3].description)
self.assertEqual(None, nav[3].state)
self.assertEqual("Task_Num_Bananas", nav[4].name)
self.assertEqual("LIKELY", nav[4].state)
self.assertEqual("EndEvent", nav[5].spec_type)
self.assertEqual("no", nav[6].description)
self.assertEqual(None, nav[6].state)
self.assertEqual("Task_Why_No_Bananas", nav[7].name)
self.assertEqual("MAYBE", nav[7].state)
def test_navigation_with_exclusive_gateway(self):
workflow = self.create_workflow('exclusive_gateway_2')
@ -129,14 +134,14 @@ class TestTasksApi(BaseTest):
workflow_api = self.get_workflow_api(workflow)
self.assertIsNotNone(workflow_api.navigation)
nav = workflow_api.navigation
self.assertEqual(7, len(nav))
self.assertEqual("Task 1", nav[0]['title'])
self.assertEqual("Which Branch?", nav[1]['title'])
self.assertEqual("a", nav[2]['title'])
self.assertEqual("Task 2a", nav[3]['title'])
self.assertEqual("b", nav[4]['title'])
self.assertEqual("Task 2b", nav[5]['title'])
self.assertEqual("Task 3", nav[6]['title'])
self.assertEqual(10, len(nav))
self.assertEqual("Task 1", nav[1].description)
self.assertEqual("Which Branch?", nav[2].description)
self.assertEqual("a", nav[3].description)
self.assertEqual("Task 2a", nav[4].description)
self.assertEqual("b", nav[5].description)
self.assertEqual("Task 2b", nav[6].description)
self.assertEqual("Task 3", nav[8].description)
def test_document_added_to_workflow_shows_up_in_file_list(self):
self.create_reference_document()
@ -385,7 +390,7 @@ class TestTasksApi(BaseTest):
navigation = workflow_api.navigation
task = workflow_api.next_task
self.assertEqual(2, len(navigation))
self.assertEqual(5, len(navigation))
self.assertEqual("UserTask", task.type)
self.assertEqual("Activity_A", task.name)
self.assertEqual("My Sub Process", task.process_name)
@ -453,7 +458,7 @@ class TestTasksApi(BaseTest):
workflow_api = self.get_workflow_api(workflow)
self.assertEqual(8, len(workflow_api.navigation))
ready_items = [nav for nav in workflow_api.navigation if nav['state'] == "READY"]
ready_items = [nav for nav in workflow_api.navigation if nav.state == "READY"]
self.assertEqual(5, len(ready_items))
self.assertEqual("UserTask", workflow_api.next_task.type)
@ -461,8 +466,8 @@ class TestTasksApi(BaseTest):
self.assertEqual("Primary Investigator", workflow_api.next_task.title)
for i in random.sample(range(5), 5):
task = TaskSchema().load(ready_items[i]['task'])
rv = self.app.put('/v1.0/workflow/%i/task/%s/set_token' % (workflow.id, task.id),
task_id = ready_items[i].task_id
rv = self.app.put('/v1.0/workflow/%i/task/%s/set_token' % (workflow.id, task_id),
headers=self.logged_in_headers(),
content_type="application/json")
self.assert_success(rv)
@ -470,7 +475,7 @@ class TestTasksApi(BaseTest):
workflow = WorkflowApiSchema().load(json_data)
data = workflow.next_task.data
data['investigator']['email'] = "dhf8r@virginia.edu"
self.complete_form(workflow, task, data)
self.complete_form(workflow, workflow.next_task, data)
#tasks = self.get_workflow_api(workflow).user_tasks
workflow = self.get_workflow_api(workflow)

View File

@ -1,6 +1,8 @@
import json
from tests.base_test import BaseTest
from crc.models.api_models import NavigationItemSchema
from crc.models.workflow import WorkflowStatus
from crc import db
from crc.api.common import ApiError
@ -62,8 +64,8 @@ class TestTasksApi(BaseTest):
workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual("supervisor", nav[1]['lane'])
self.assertEqual(9, len(nav))
self.assertEqual("supervisor", nav[2].lane)
def test_get_outstanding_tasks_awaiting_current_user(self):
submitter = self.create_user(uid='lje5u')
@ -121,12 +123,12 @@ class TestTasksApi(BaseTest):
# Navigation as Submitter with ready task.
workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual('READY', nav[0]['state']) # First item is ready, no progress yet.
self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway, and belongs to no one, and is locked.
self.assertEqual('NOOP', nav[3]['state']) # Approved Path, has no operation
self.assertEqual('NOOP', nav[4]['state']) # Rejected Path, has no operation.
self.assertEqual(9, len(nav))
self.assertEqual('READY', nav[1].state) # First item is ready, no progress yet.
self.assertEqual('LOCKED', nav[2].state) # Second item is locked, it is the review and doesn't belong to this user.
# third item is a gateway, and belongs to no one
self.assertEqual(None, nav[4].state) # Approved Path, has no operation
self.assertEqual(None, nav[6].state) # Rejected Path, has no operation.
self.assertEqual('READY', workflow_api.next_task.state)
# Navigation as Submitter after handoff to supervisor
@ -134,9 +136,9 @@ class TestTasksApi(BaseTest):
data['supervisor'] = supervisor.uid
workflow_api = self.complete_form(workflow, workflow_api.next_task, data, user_uid=submitter.uid)
nav = workflow_api.navigation
self.assertEqual('COMPLETED', nav[0]['state']) # First item is ready, no progress yet.
self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway, and belongs to no one, and is locked.
self.assertEqual('COMPLETED', nav[1].state) # First item is ready, no progress yet.
self.assertEqual('LOCKED', nav[2].state) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('MAYBE', nav[7].state) # third item is a gateway, and belongs to no one, and is locked.
self.assertEqual('LOCKED', workflow_api.next_task.state)
# In the event the next task is locked, we should say something sensible here.
# It is possible to look at the role of the task, and say The next task "TASK TITLE" will
@ -149,10 +151,10 @@ class TestTasksApi(BaseTest):
# Navigation as Supervisor
workflow_api = self.get_workflow_api(workflow, user_uid=supervisor.uid)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual('LOCKED', nav[0]['state']) # First item belongs to the submitter, and is locked.
self.assertEqual('READY', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway, and belongs to no one, and is locked.
self.assertEqual(9, len(nav))
self.assertEqual('LOCKED', nav[1].state) # First item belongs to the submitter, and is locked.
self.assertEqual('READY', nav[2].state) # Second item is ready, as we are now the supervisor.
self.assertEqual('LOCKED', nav[7].state) # Feedback is locked.
self.assertEqual('READY', workflow_api.next_task.state)
data = workflow_api.next_task.data
@ -161,28 +163,28 @@ class TestTasksApi(BaseTest):
# Navigation as Supervisor, after completing task.
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual('LOCKED', nav[0]['state']) # First item belongs to the submitter, and is locked.
self.assertEqual('COMPLETED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('COMPLETED', nav[2]['state']) # third item is a gateway, and is now complete.
self.assertEqual(9, len(nav))
self.assertEqual('LOCKED', nav[1].state) # First item belongs to the submitter, and is locked.
self.assertEqual('COMPLETED', nav[2].state) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[7].state) # Feedback is LOCKED
self.assertEqual('LOCKED', workflow_api.next_task.state)
# Navigation as Submitter, coming back in to a rejected workflow to view the rejection message.
workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual('COMPLETED', nav[0]['state']) # First item belongs to the submitter, and is locked.
self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway belonging to the supervisor, and is locked.
self.assertEqual(9, len(nav))
self.assertEqual('COMPLETED', nav[1].state) # First item belongs to the submitter, and is locked.
self.assertEqual('LOCKED', nav[2].state) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('READY', nav[7].state) # Feedbck is now READY
self.assertEqual('READY', workflow_api.next_task.state)
# Navigation as Submitter, re-completing the original request a second time, and sending it for review.
workflow_api = self.complete_form(workflow, workflow_api.next_task, data, user_uid=submitter.uid)
nav = workflow_api.navigation
self.assertEqual(5, len(nav))
self.assertEqual('READY', nav[0]['state']) # When you loop back the task is again in the ready state.
self.assertEqual('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('LOCKED', nav[2]['state']) # third item is a gateway belonging to the supervisor, and is locked.
self.assertEqual(9, len(nav))
self.assertEqual('READY', nav[1].state) # When you loop back the task is again in the ready state.
self.assertEqual('LOCKED', nav[2].state) # Second item is locked, it is the review and doesn't belong to this user.
self.assertEqual('COMPLETED', nav[7].state) # Feedback is completed
self.assertEqual('READY', workflow_api.next_task.state)
data["favorite_color"] = "blue"

View File

@ -171,7 +171,7 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
# Assure navigation picks up the label of the current element variable.
nav = WorkflowService.processor_to_workflow_api(processor, task).navigation
self.assertEqual("Primary Investigator", nav[2].title)
self.assertEqual("Primary Investigator", nav[2].description)
task.update_data({"investigator": {"email": "dhf8r@virginia.edu"}})
processor.complete_task(task)