Additional fixes to Navigation to allow a nested navigation structure.
This commit is contained in:
parent
93b12a8e82
commit
02ea414b94
|
@ -80,10 +80,10 @@
|
|||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:1f422849db327d534e3d0c5f02a263458c3955ec0aae4ff09b95f195c59f4edd",
|
||||
"sha256:f05def092c44fbf25834a51509ef6e631dc19765ab8a57b4e7ab85531f0a9cf4"
|
||||
"sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c",
|
||||
"sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"
|
||||
],
|
||||
"version": "==2020.11.8"
|
||||
"version": "==2020.12.5"
|
||||
},
|
||||
"cffi": {
|
||||
"hashes": [
|
||||
|
@ -557,33 +557,33 @@
|
|||
},
|
||||
"pandas": {
|
||||
"hashes": [
|
||||
"sha256:09e0503758ad61afe81c9069505f8cb8c1e36ea8cc1e6826a95823ef5b327daf",
|
||||
"sha256:0a11a6290ef3667575cbd4785a1b62d658c25a2fd70a5adedba32e156a8f1773",
|
||||
"sha256:0d9a38a59242a2f6298fff45d09768b78b6eb0c52af5919ea9e45965d7ba56d9",
|
||||
"sha256:112c5ba0f9ea0f60b2cc38c25f87ca1d5ca10f71efbee8e0f1bee9cf584ed5d5",
|
||||
"sha256:185cf8c8f38b169dbf7001e1a88c511f653fbb9dfa3e048f5e19c38049e991dc",
|
||||
"sha256:3aa8e10768c730cc1b610aca688f588831fa70b65a26cb549fbb9f35049a05e0",
|
||||
"sha256:41746d520f2b50409dffdba29a15c42caa7babae15616bcf80800d8cfcae3d3e",
|
||||
"sha256:43cea38cbcadb900829858884f49745eb1f42f92609d368cabcc674b03e90efc",
|
||||
"sha256:5378f58172bd63d8c16dd5d008d7dcdd55bf803fcdbe7da2dcb65dbbf322f05b",
|
||||
"sha256:54404abb1cd3f89d01f1fb5350607815326790efb4789be60508f458cdd5ccbf",
|
||||
"sha256:5dac3aeaac5feb1016e94bde851eb2012d1733a222b8afa788202b836c97dad5",
|
||||
"sha256:5fdb2a61e477ce58d3f1fdf2470ee142d9f0dde4969032edaf0b8f1a9dafeaa2",
|
||||
"sha256:6613c7815ee0b20222178ad32ec144061cb07e6a746970c9160af1ebe3ad43b4",
|
||||
"sha256:6d2b5b58e7df46b2c010ec78d7fb9ab20abf1d306d0614d3432e7478993fbdb0",
|
||||
"sha256:8a5d7e57b9df2c0a9a202840b2881bb1f7a648eba12dd2d919ac07a33a36a97f",
|
||||
"sha256:8b4c2055ebd6e497e5ecc06efa5b8aa76f59d15233356eb10dad22a03b757805",
|
||||
"sha256:a15653480e5b92ee376f8458197a58cca89a6e95d12cccb4c2d933df5cecc63f",
|
||||
"sha256:a7d2547b601ecc9a53fd41561de49a43d2231728ad65c7713d6b616cd02ddbed",
|
||||
"sha256:a979d0404b135c63954dea79e6246c45dd45371a88631cdbb4877d844e6de3b6",
|
||||
"sha256:b1f8111635700de7ac350b639e7e452b06fc541a328cf6193cf8fc638804bab8",
|
||||
"sha256:c5a3597880a7a29a31ebd39b73b2c824316ae63a05c3c8a5ce2aea3fc68afe35",
|
||||
"sha256:c681e8fcc47a767bf868341d8f0d76923733cbdcabd6ec3a3560695c69f14a1e",
|
||||
"sha256:cf135a08f306ebbcfea6da8bf775217613917be23e5074c69215b91e180caab4",
|
||||
"sha256:e2b8557fe6d0a18db4d61c028c6af61bfed44ef90e419ed6fadbdc079eba141e"
|
||||
"sha256:0a643bae4283a37732ddfcecab3f62dd082996021b980f580903f4e8e01b3c5b",
|
||||
"sha256:0de3ddb414d30798cbf56e642d82cac30a80223ad6fe484d66c0ce01a84d6f2f",
|
||||
"sha256:19a2148a1d02791352e9fa637899a78e371a3516ac6da5c4edc718f60cbae648",
|
||||
"sha256:21b5a2b033380adbdd36b3116faaf9a4663e375325831dac1b519a44f9e439bb",
|
||||
"sha256:24c7f8d4aee71bfa6401faeba367dd654f696a77151a8a28bc2013f7ced4af98",
|
||||
"sha256:26fa92d3ac743a149a31b21d6f4337b0594b6302ea5575b37af9ca9611e8981a",
|
||||
"sha256:2860a97cbb25444ffc0088b457da0a79dc79f9c601238a3e0644312fcc14bf11",
|
||||
"sha256:2b1c6cd28a0dfda75c7b5957363333f01d370936e4c6276b7b8e696dd500582a",
|
||||
"sha256:2c2f7c670ea4e60318e4b7e474d56447cf0c7d83b3c2a5405a0dbb2600b9c48e",
|
||||
"sha256:3be7a7a0ca71a2640e81d9276f526bca63505850add10206d0da2e8a0a325dae",
|
||||
"sha256:4c62e94d5d49db116bef1bd5c2486723a292d79409fc9abd51adf9e05329101d",
|
||||
"sha256:5008374ebb990dad9ed48b0f5d0038124c73748f5384cc8c46904dace27082d9",
|
||||
"sha256:5447ea7af4005b0daf695a316a423b96374c9c73ffbd4533209c5ddc369e644b",
|
||||
"sha256:573fba5b05bf2c69271a32e52399c8de599e4a15ab7cec47d3b9c904125ab788",
|
||||
"sha256:5a780260afc88268a9d3ac3511d8f494fdcf637eece62fb9eb656a63d53eb7ca",
|
||||
"sha256:70865f96bb38fec46f7ebd66d4b5cfd0aa6b842073f298d621385ae3898d28b5",
|
||||
"sha256:731568be71fba1e13cae212c362f3d2ca8932e83cb1b85e3f1b4dd77d019254a",
|
||||
"sha256:b61080750d19a0122469ab59b087380721d6b72a4e7d962e4d7e63e0c4504814",
|
||||
"sha256:bf23a3b54d128b50f4f9d4675b3c1857a688cc6731a32f931837d72effb2698d",
|
||||
"sha256:c16d59c15d946111d2716856dd5479221c9e4f2f5c7bc2d617f39d870031e086",
|
||||
"sha256:c61c043aafb69329d0f961b19faa30b1dab709dd34c9388143fc55680059e55a",
|
||||
"sha256:c94ff2780a1fd89f190390130d6d36173ca59fcfb3fe0ff596f9a56518191ccb",
|
||||
"sha256:edda9bacc3843dfbeebaf7a701763e68e741b08fccb889c003b0a52f0ee95782",
|
||||
"sha256:f10fc41ee3c75a474d3bdf68d396f10782d013d7f67db99c0efbfd0acb99701b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.1.4"
|
||||
"version": "==1.1.5"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
"hashes": [
|
||||
|
@ -650,10 +650,10 @@
|
|||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:381985fcc551eb9d37c52088a32914e00517e57f4a21609f48141ba08e193fa0",
|
||||
"sha256:88a0bbcd659fcb9573703957c6b9cff9fab7295e6e76db54c9d00ae42df32773"
|
||||
"sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716",
|
||||
"sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"
|
||||
],
|
||||
"version": "==2.7.2"
|
||||
"version": "==2.7.3"
|
||||
},
|
||||
"pyjwt": {
|
||||
"hashes": [
|
||||
|
@ -839,7 +839,7 @@
|
|||
},
|
||||
"spiffworkflow": {
|
||||
"git": "https://github.com/sartography/SpiffWorkflow.git",
|
||||
"ref": "cdab930848493d74250224f1956177fee231a5b7"
|
||||
"ref": "71f75612779822166f3fc97ca39bb4630202af9d"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
|
|
|
@ -144,21 +144,24 @@ class TaskSchema(ma.Schema):
|
|||
class NavigationItemSchema(ma.Schema):
|
||||
class Meta:
|
||||
fields = ["spec_id", "name", "spec_type", "task_id", "description", "backtracks", "indent",
|
||||
"lane", "state"]
|
||||
"lane", "state", "children"]
|
||||
unknown = INCLUDE
|
||||
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)
|
||||
task_id = marshmallow.fields.String(required=False, allow_none=True)
|
||||
children = marshmallow.fields.List(marshmallow.fields.Nested(lambda: NavigationItemSchema()))
|
||||
|
||||
@marshmallow.post_load
|
||||
def make_nav(self, data, **kwargs):
|
||||
state = data.pop('state', None)
|
||||
task_id = data.pop('task_id', None)
|
||||
children = data.pop('children', [])
|
||||
item = NavItem(**data)
|
||||
item.state = state
|
||||
item.task_id = task_id
|
||||
item.children = children
|
||||
return item
|
||||
|
||||
class WorkflowApi(object):
|
||||
|
|
|
@ -6,7 +6,7 @@ from datetime import datetime
|
|||
from typing import List
|
||||
|
||||
import jinja2
|
||||
from SpiffWorkflow import Task as SpiffTask, WorkflowException
|
||||
from SpiffWorkflow import Task as SpiffTask, WorkflowException, NavItem
|
||||
from SpiffWorkflow.bpmn.specs.EndEvent import EndEvent
|
||||
from SpiffWorkflow.bpmn.specs.ManualTask import ManualTask
|
||||
from SpiffWorkflow.bpmn.specs.MultiInstanceTask import MultiInstanceTask
|
||||
|
@ -14,7 +14,7 @@ from SpiffWorkflow.bpmn.specs.ScriptTask import ScriptTask
|
|||
from SpiffWorkflow.bpmn.specs.StartEvent import StartEvent
|
||||
from SpiffWorkflow.bpmn.specs.UserTask import UserTask
|
||||
from SpiffWorkflow.dmn.specs.BusinessRuleTask import BusinessRuleTask
|
||||
from SpiffWorkflow.specs import CancelTask, StartTask
|
||||
from SpiffWorkflow.specs import CancelTask, StartTask, MultiChoice
|
||||
from SpiffWorkflow.util.deep_merge import DeepMerge
|
||||
from jinja2 import Template
|
||||
|
||||
|
@ -319,25 +319,9 @@ class WorkflowService(object):
|
|||
"""Returns an API model representing the state of the current workflow, if requested, and
|
||||
possible, next_task is set to the current_task."""
|
||||
|
||||
nav_dict = processor.bpmn_workflow.get_nav_list()
|
||||
navigation = processor.bpmn_workflow.get_deep_nav_list()
|
||||
WorkflowService.update_navigation(navigation, processor)
|
||||
|
||||
# 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 spiff_task:
|
||||
# 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
|
||||
else:
|
||||
# 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(
|
||||
|
@ -366,6 +350,29 @@ class WorkflowService(object):
|
|||
workflow_api.next_task.state = WorkflowService.TASK_STATE_LOCKED
|
||||
return workflow_api
|
||||
|
||||
@staticmethod
|
||||
def update_navigation(navigation: List[NavItem], processor: WorkflowProcessor):
|
||||
# Recursive function to walk down through children, and clean up descriptions, and statuses
|
||||
for nav_item in navigation:
|
||||
spiff_task = processor.bpmn_workflow.get_task(nav_item.task_id)
|
||||
if spiff_task:
|
||||
# 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 (isinstance(spiff_task.task_spec, UserTask) or isinstance(spiff_task.task_spec, ManualTask)) \
|
||||
and not UserService.in_list(user_uids, allow_admin_impersonate=True):
|
||||
nav_item.state = WorkflowService.TASK_STATE_LOCKED
|
||||
else:
|
||||
# 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]
|
||||
|
||||
# Recurse here
|
||||
WorkflowService.update_navigation(nav_item.children, processor)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_previously_submitted_data(workflow_id, spiff_task):
|
||||
""" If the user has completed this task previously, find the form data for the last submission."""
|
||||
|
@ -393,6 +400,7 @@ class WorkflowService(object):
|
|||
return {}
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def spiff_task_to_api_task(spiff_task, add_docs_and_forms=False):
|
||||
task_type = spiff_task.task_spec.__class__.__name__
|
||||
|
|
|
@ -113,19 +113,20 @@ class TestTasksApi(BaseTest):
|
|||
|
||||
self.assertIsNotNone(workflow_api.navigation)
|
||||
nav = workflow_api.navigation
|
||||
self.assertEqual(9, len(nav))
|
||||
self.assertEqual(3, 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)
|
||||
self.assertEqual("LIKELY", nav[2].state)
|
||||
|
||||
self.assertEqual("yes", nav[2].children[0].description)
|
||||
self.assertEqual("LIKELY", nav[2].children[0].state)
|
||||
self.assertEqual("of Bananas", nav[2].children[0].children[0].description)
|
||||
self.assertEqual("EndEvent", nav[2].children[0].children[1].spec_type)
|
||||
|
||||
self.assertEqual("no", nav[2].children[1].description)
|
||||
self.assertEqual("MAYBE", nav[2].children[1].state)
|
||||
self.assertEqual("no bananas", nav[2].children[1].children[0].description)
|
||||
self.assertEqual("EndEvent", nav[2].children[1].children[1].spec_type)
|
||||
|
||||
def test_navigation_with_exclusive_gateway(self):
|
||||
workflow = self.create_workflow('exclusive_gateway_2')
|
||||
|
@ -134,14 +135,17 @@ class TestTasksApi(BaseTest):
|
|||
workflow_api = self.get_workflow_api(workflow)
|
||||
self.assertIsNotNone(workflow_api.navigation)
|
||||
nav = workflow_api.navigation
|
||||
self.assertEqual(10, len(nav))
|
||||
self.assertEqual(6, 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)
|
||||
self.assertEqual("a", nav[2].children[0].description)
|
||||
self.assertEqual("Task 2a", nav[2].children[0].children[0].description)
|
||||
self.assertEqual("b", nav[2].children[1].description)
|
||||
self.assertEqual("Task 2b", nav[2].children[1].children[0].description)
|
||||
self.assertEqual(None, nav[3].description)
|
||||
self.assertEqual("Task 3", nav[4].description)
|
||||
self.assertEqual("EndEvent", nav[5].spec_type)
|
||||
|
||||
|
||||
def test_document_added_to_workflow_shows_up_in_file_list(self):
|
||||
self.create_reference_document()
|
||||
|
@ -390,7 +394,7 @@ class TestTasksApi(BaseTest):
|
|||
navigation = workflow_api.navigation
|
||||
task = workflow_api.next_task
|
||||
|
||||
self.assertEqual(5, len(navigation))
|
||||
self.assertEqual(4, len(navigation))
|
||||
self.assertEqual("UserTask", task.type)
|
||||
self.assertEqual("Activity_A", task.name)
|
||||
self.assertEqual("My Sub Process", task.process_name)
|
||||
|
|
|
@ -64,7 +64,7 @@ class TestTasksApi(BaseTest):
|
|||
workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid)
|
||||
|
||||
nav = workflow_api.navigation
|
||||
self.assertEqual(9, len(nav))
|
||||
self.assertEqual(4, len(nav))
|
||||
self.assertEqual("supervisor", nav[2].lane)
|
||||
|
||||
def test_get_outstanding_tasks_awaiting_current_user(self):
|
||||
|
@ -123,12 +123,10 @@ 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(9, len(nav))
|
||||
self.assertEqual(4, 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('LIKELY', nav[3].state) # Third item is a gateway, which contains things that are also locked.
|
||||
self.assertEqual('READY', workflow_api.next_task.state)
|
||||
|
||||
# Navigation as Submitter after handoff to supervisor
|
||||
|
@ -138,8 +136,7 @@ class TestTasksApi(BaseTest):
|
|||
nav = workflow_api.navigation
|
||||
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)
|
||||
self.assertEqual('LIKELY', nav[3].state) # third item is a gateway, and belongs to no one
|
||||
# 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
|
||||
# be handled by 'dhf8r', who is full-filling the role of supervisor. the Task Data
|
||||
|
@ -151,10 +148,9 @@ class TestTasksApi(BaseTest):
|
|||
# Navigation as Supervisor
|
||||
workflow_api = self.get_workflow_api(workflow, user_uid=supervisor.uid)
|
||||
nav = workflow_api.navigation
|
||||
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('LIKELY', nav[3].state) # Feedback is locked.
|
||||
self.assertEqual('READY', workflow_api.next_task.state)
|
||||
|
||||
data = workflow_api.next_task.data
|
||||
|
@ -163,28 +159,37 @@ class TestTasksApi(BaseTest):
|
|||
|
||||
# Navigation as Supervisor, after completing task.
|
||||
nav = workflow_api.navigation
|
||||
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('READY', nav[3].state) # Gateway is ready, and should be unfolded
|
||||
self.assertEqual(None, nav[3].children[0].state) # sequence flow for approved is none - we aren't going this way.
|
||||
self.assertEqual('READY', nav[3].children[1].state) # sequence flow for denied is ready
|
||||
self.assertEqual('LOCKED', nav[3].children[1].children[0].state) # Feedback is locked, it belongs to submitter
|
||||
self.assertEqual('LOCKED', nav[3].children[1].children[0].state) # Approval is locked, it belongs to the submitter
|
||||
|
||||
|
||||
|
||||
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(9, len(nav))
|
||||
self.assertEqual(4, 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)
|
||||
self.assertEqual('READY', nav[3].state)
|
||||
self.assertEqual(None, nav[3].children[0].state) # sequence flow for approved is none - we aren't going this way.
|
||||
self.assertEqual('READY', nav[3].children[1].state) # sequence flow for denied is ready
|
||||
self.assertEqual('READY', nav[3].children[1].children[0].state) # Feedback is locked, it belongs to submitter
|
||||
self.assertEqual('READY', nav[3].children[1].children[0].state) # Approval is locked, it belongs to the submitter
|
||||
|
||||
|
||||
# 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(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('COMPLETED', nav[3].state) # Feedback is completed
|
||||
self.assertEqual('READY', workflow_api.next_task.state)
|
||||
|
||||
data["favorite_color"] = "blue"
|
||||
|
|
|
@ -52,11 +52,11 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
task_list = processor.get_ready_user_tasks()
|
||||
processor.complete_task(task_list[0])
|
||||
processor.do_engine_steps()
|
||||
nav_list = processor.bpmn_workflow.get_nav_list()
|
||||
nav_list = processor.bpmn_workflow.get_flat_nav_list()
|
||||
processor.save()
|
||||
# reload after save
|
||||
processor = WorkflowProcessor(workflow_spec_model)
|
||||
nav_list2 = processor.bpmn_workflow.get_nav_list()
|
||||
nav_list2 = processor.bpmn_workflow.get_flat_nav_list()
|
||||
self.assertEqual(nav_list,nav_list2)
|
||||
|
||||
@patch('crc.services.study_service.StudyService.get_investigators')
|
||||
|
@ -158,7 +158,7 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
self.assertEqual(3, len(next_user_tasks))
|
||||
# There should be six tasks in the navigation: start event, the script task, end event, and three tasks
|
||||
# for the three executions of hte multi-instance.
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_nav_list()))
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_flat_nav_list()))
|
||||
|
||||
# We can complete the tasks out of order.
|
||||
task = next_user_tasks[2]
|
||||
|
@ -176,7 +176,7 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
task.update_data({"investigator": {"email": "dhf8r@virginia.edu"}})
|
||||
processor.complete_task(task)
|
||||
processor.do_engine_steps()
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_nav_list()))
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_flat_nav_list()))
|
||||
|
||||
task = next_user_tasks[0]
|
||||
api_task = WorkflowService.spiff_task_to_api_task(task)
|
||||
|
@ -184,7 +184,7 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
task.update_data({"investigator":{"email":"asd3v@virginia.edu"}})
|
||||
processor.complete_task(task)
|
||||
processor.do_engine_steps()
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_nav_list()))
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_flat_nav_list()))
|
||||
|
||||
task = next_user_tasks[1]
|
||||
api_task = WorkflowService.spiff_task_to_api_task(task)
|
||||
|
@ -192,7 +192,7 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
task.update_data({"investigator":{"email":"asdf32@virginia.edu"}})
|
||||
processor.complete_task(task)
|
||||
processor.do_engine_steps()
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_nav_list()))
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_flat_nav_list()))
|
||||
|
||||
# Completing the tasks out of order, still provides the correct information.
|
||||
expected = self.mock_investigator_response
|
||||
|
@ -203,4 +203,4 @@ class TestWorkflowProcessorMultiInstance(BaseTest):
|
|||
task.data['StudyInfo']['investigators'])
|
||||
|
||||
self.assertEqual(WorkflowStatus.complete, processor.get_status())
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_nav_list()))
|
||||
self.assertEqual(6, len(processor.bpmn_workflow.get_flat_nav_list()))
|
||||
|
|
Loading…
Reference in New Issue