diff --git a/crc/api/workflow.py b/crc/api/workflow.py
index e7a4d1ca..0c94857f 100644
--- a/crc/api/workflow.py
+++ b/crc/api/workflow.py
@@ -6,7 +6,7 @@ from crc import session
from crc.api.common import ApiError, ApiErrorSchema
from crc.models.api_models import WorkflowApiSchema
from crc.models.study import StudyModel, WorkflowMetadata, StudyStatus
-from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema
+from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema, TaskAction
from crc.models.workflow import WorkflowModel, WorkflowSpecInfoSchema, WorkflowSpecCategorySchema
from crc.services.error_service import ValidationErrorService
from crc.services.lookup_service import LookupService
@@ -205,8 +205,10 @@ def get_workflow(workflow_id, do_engine_steps=True):
def restart_workflow(workflow_id, clear_data=False, delete_files=False):
"""Restart a workflow with the latest spec.
Clear data allows user to restart the workflow without previous data."""
+ # fixme: remove delete_files arg, clear_data is the only one respected.
workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(id=workflow_id).first()
- processor = WorkflowProcessor.reset(workflow_model, clear_data=clear_data, delete_files=delete_files)
+ WorkflowProcessor.reset(workflow_model, clear_data=clear_data)
+ processor = WorkflowProcessor(workflow_model)
processor.do_engine_steps()
processor.save()
WorkflowService.update_task_assignments(processor)
@@ -269,7 +271,7 @@ def set_current_task(workflow_id, task_id):
spiff_task.reset_token({}, reset_data=True) # Don't try to copy the existing data back into this task.
processor.save()
- WorkflowService.log_task_action(user_uid, processor, spiff_task, WorkflowService.TASK_ACTION_TOKEN_RESET)
+ WorkflowService.log_task_action(user_uid, processor, spiff_task, TaskAction.TOKEN_RESET.value)
WorkflowService.update_task_assignments(processor)
workflow_api_model = WorkflowService.processor_to_workflow_api(processor, spiff_task)
@@ -327,7 +329,7 @@ def __update_task(processor, task, data, user):
# Log the action before doing the engine steps, as doing so could effect the state of the task
# the workflow could wrap around in the ngine steps, and the task could jump from being completed to
# another state. What we are logging here is the completion.
- WorkflowService.log_task_action(user.uid, processor, task, WorkflowService.TASK_ACTION_COMPLETE)
+ WorkflowService.log_task_action(user.uid, processor, task, TaskAction.COMPLETE.value)
processor.do_engine_steps()
processor.save()
diff --git a/crc/models/task_event.py b/crc/models/task_event.py
index 103c6cb0..f8ce379a 100644
--- a/crc/models/task_event.py
+++ b/crc/models/task_event.py
@@ -1,3 +1,5 @@
+import enum
+
from marshmallow import INCLUDE, fields
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema
@@ -7,6 +9,13 @@ from crc.models.workflow import WorkflowModel
from crc.services.ldap_service import LdapService
from sqlalchemy import func
+class TaskAction(enum.Enum):
+ COMPLETE = "COMPLETE"
+ TOKEN_RESET = "TOKEN_RESET"
+ HARD_RESET = "HARD_RESET"
+ SOFT_RESET = "SOFT_RESET"
+ ASSIGNMENT = "ASSIGNMENT" # Whenever the lane changes between tasks we assign the task to specific user.
+
class TaskEventModel(db.Model):
__tablename__ = 'task_event'
diff --git a/crc/scripts/delete_task_data.py b/crc/scripts/delete_task_data.py
index 7c7cbe60..83604662 100644
--- a/crc/scripts/delete_task_data.py
+++ b/crc/scripts/delete_task_data.py
@@ -2,7 +2,7 @@ from crc import session
from crc.api.common import ApiError
from crc.models.data_store import DataStoreModel
from crc.models.file import FileModel
-from crc.models.task_event import TaskEventModel
+from crc.models.task_event import TaskEventModel, TaskAction
from crc.scripts.script import Script
from crc.services.document_service import DocumentService
from crc.services.user_file_service import UserFileService
@@ -36,7 +36,7 @@ class DeleteTaskData(Script):
# delete task events
session.query(TaskEventModel).filter(TaskEventModel.workflow_id == workflow_id).filter(
TaskEventModel.study_id == study_id).filter(TaskEventModel.task_name == task_spec_name).filter_by(
- action=WorkflowService.TASK_ACTION_COMPLETE).delete()
+ action=TaskAction.COMPLETE.value).delete()
files_to_delete = session.query(FileModel). \
filter(FileModel.workflow_id == workflow_id). \
diff --git a/crc/scripts/reset_workflow.py b/crc/scripts/reset_workflow.py
index cb3cc368..da15e125 100644
--- a/crc/scripts/reset_workflow.py
+++ b/crc/scripts/reset_workflow.py
@@ -9,34 +9,42 @@ from crc.services.workflow_spec_service import WorkflowSpecService
class ResetWorkflow(Script):
def get_description(self):
- return """Reset a workflow. Run by master workflow.
+ return """Reset a workflow. Run by mas vftgv ter workflow.
Designed for completed workflows where we need to force rerunning the workflow.
I.e., a new PI"""
+ def get_spec(self, *args, **kwargs):
+ workflow_spec_id = None
+ if 'workflow_spec_id' in kwargs.keys():
+ workflow_spec_id = kwargs['workflow_spec_id']
+ elif len(args) > 0:
+ workflow_spec_id = args[0]
+
+ if not workflow_spec_id:
+ raise ApiError(code='missing_workflow_id',
+ message='Reset workflow requires a workflow_spec_id')
+
+ workflow_spec = WorkflowSpecService().get_spec(workflow_spec_id)
+ if not workflow_spec:
+ raise ApiError(code='missing_workflow_spec',
+ message=f'No workflow spec found with the \
+ id: {workflow_spec_id}')
+
+ return workflow_spec
+
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
- return hasattr(kwargs, 'reset_id')
+ self.get_spec(*args, **kwargs) # Just assure we can find the workflow spec.
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
-
- if 'reset_id' in kwargs.keys():
- reset_id = kwargs['reset_id']
- workflow_spec = WorkflowSpecService().get_spec(reset_id)
- if workflow_spec:
- workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(
- workflow_spec_id=workflow_spec.id,
- study_id=study_id).first()
- if workflow_model:
- workflow_processor = WorkflowProcessor.reset(workflow_model, clear_data=False, delete_files=False)
- return workflow_processor
- else:
- raise ApiError(code='missing_workflow_model',
- message=f'No WorkflowModel returned. \
- workflow_spec_id: {workflow_spec.id} \
- study_id: {study_id}')
- else:
- raise ApiError(code='missing_workflow_spec',
- message=f'No WorkflowSpecModel returned. \
- id: {workflow_id}')
+ if 'clear_data' in kwargs.keys():
+ clear_data = bool(kwargs['clear_data'])
else:
- raise ApiError(code='missing_workflow_id',
- message='Reset workflow requires a workflow id')
+ clear_data = False
+
+ workflow_spec = self.get_spec(*args, **kwargs)
+ if workflow_spec:
+ workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(
+ workflow_spec_id=workflow_spec.id,
+ study_id=study_id).first()
+ if workflow_model:
+ WorkflowProcessor.reset(workflow_model, clear_data=clear_data)
diff --git a/crc/scripts/start_workflow.py b/crc/scripts/start_workflow.py
index 0f409d27..9e9197ca 100644
--- a/crc/scripts/start_workflow.py
+++ b/crc/scripts/start_workflow.py
@@ -9,68 +9,42 @@ from crc.services.workflow_service import WorkflowService
class StartWorkflow(Script):
- @staticmethod
- def get_workflow(workflow_id):
- workflow_model: WorkflowModel = session.query(WorkflowModel).filter_by(id=workflow_id).first()
- processor = WorkflowProcessor(workflow_model)
-
- processor.do_engine_steps()
- processor.save()
- WorkflowService.update_task_assignments(processor)
-
- workflow_api_model = WorkflowService.processor_to_workflow_api(processor)
- return WorkflowApiSchema().dump(workflow_api_model)
-
def get_description(self):
return """Script to start a workflow programmatically.
It requires a workflow_spec_id.
It accepts the workflow_spec_id as a positional argument
or with the keyword 'workflow_spec_id'"""
- def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
+ def get_workflow(self, study_id, *args, **kwargs):
if len(args) == 1 or 'workflow_spec_id' in kwargs:
if 'workflow_spec_id' in kwargs:
workflow_spec_id = kwargs['workflow_spec_id']
else:
workflow_spec_id = args[0]
-
- workflow_api = WorkflowApi(1234,
- WorkflowStatus('user_input_required'),
- 'next_task',
- 'navigation',
- workflow_spec_id,
- 'total_tasks',
- 'completed_tasks',
- 'last_updated',
- 'is_review',
- 'title',
- study_id)
- return WorkflowApiSchema().dump(workflow_api)
-
else:
raise ApiError(code='missing_parameter',
message=f'The start_workflow script requires a workflow id')
+ workflow = session.query(WorkflowModel).\
+ filter(WorkflowModel.study_id==study_id).\
+ filter(WorkflowModel.workflow_spec_id==workflow_spec_id).\
+ first()
+
+ if not(workflow):
+ raise ApiError(code='unknown_workflow',
+ message=f"We could not find a workflow with workflow_spec_id '{workflow_spec_id}'.")
+
+ return workflow
+
+ def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
+ self.get_workflow(study_id, *args, **kwargs)
+
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
- if len(args) == 1 or 'workflow_spec_id' in kwargs:
- if 'workflow_spec_id' in kwargs:
- workflow_spec_id = kwargs['workflow_spec_id']
- else:
- workflow_spec_id = args[0]
+ workflow_model = self.get_workflow(study_id, *args, **kwargs)
+ if workflow_model.status != WorkflowStatus.not_started:
+ return # This workflow has al ready started, don't execute these next very expensive lines.
+ processor = WorkflowProcessor(workflow_model)
+ processor.do_engine_steps()
+ processor.save()
+ WorkflowService.update_task_assignments(processor)
- workflow = session.query(WorkflowModel).\
- filter(WorkflowModel.study_id==study_id).\
- filter(WorkflowModel.workflow_spec_id==workflow_spec_id).\
- first()
-
- # Optimization -> only do this if the workflow is not started.
- if workflow:
- workflow_api = self.get_workflow(workflow.id)
- return workflow_api
- else:
- raise ApiError(code='unknown_workflow',
- message=f"We could not find a workflow with workflow_spec_id '{workflow_spec_id}'.")
-
- else:
- raise ApiError(code='missing_parameter',
- message=f'The start_workflow script requires a workflow id')
diff --git a/crc/services/data_store_service.py b/crc/services/data_store_service.py
index 249065fa..ba168bf2 100644
--- a/crc/services/data_store_service.py
+++ b/crc/services/data_store_service.py
@@ -146,9 +146,9 @@ class DataStoreBase(object):
elif study_id:
query = query.filter(DataStoreModel.study_id == study_id)
record = query.first()
- session.delete(record)
- session.commit()
- # return record
+ if record is not None:
+ session.delete(record)
+ session.commit()
@staticmethod
def delete_extra_data_stores(records):
diff --git a/crc/services/workflow_processor.py b/crc/services/workflow_processor.py
index 6fd91fe7..0b4ad1a9 100644
--- a/crc/services/workflow_processor.py
+++ b/crc/services/workflow_processor.py
@@ -23,7 +23,7 @@ from SpiffWorkflow.specs import WorkflowSpec
from crc import session
from crc.api.common import ApiError
from crc.models.file import FileModel, FileType, File
-from crc.models.task_event import TaskEventModel
+from crc.models.task_event import TaskEventModel, TaskAction
from crc.models.user import UserModelSchema
from crc.models.workflow import WorkflowStatus, WorkflowModel, WorkflowSpecInfo
from crc.scripts.script import Script
@@ -175,7 +175,13 @@ class WorkflowProcessor(object):
task.data['current_user'] = current_user_data
@staticmethod
- def reset(workflow_model, clear_data=False, delete_files=False):
+ def reset(workflow_model, clear_data=False):
+ """Resets the workflow back to an unstarted state - where nothing has
+ happened yet. If clear_data is set to false, then the information
+ previously used in forms will be re-populated when the form is re-
+ displayed, and any files that were updated will remain in place, otherwise
+ files will also be cleared out."""
+
# Try to execute a cancel notify
try:
bpmn_workflow = WorkflowProcessor.__get_bpmn_workflow(workflow_model)
@@ -186,19 +192,27 @@ class WorkflowProcessor(object):
f" state. An %s error occured with the following information: %s" %
(workflow_model.id, e.__class__.__name__, str(e)))
workflow_model.bpmn_workflow_json = None
+ workflow_model.status = WorkflowStatus.not_started
+
+ # clear out any task assignments
+ session.query(TaskEventModel). \
+ filter(TaskEventModel.workflow_id == workflow_model.id). \
+ filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).delete()
+
if clear_data:
- # Clear form_data from task_events
+ # Clear out data in previous task events
task_events = session.query(TaskEventModel). \
filter(TaskEventModel.workflow_id == workflow_model.id).all()
for task_event in task_events:
task_event.form_data = {}
session.add(task_event)
- if delete_files:
+ # Remove any uploaded files.
files = FileModel.query.filter(FileModel.workflow_id == workflow_model.id).all()
for file in files:
UserFileService.delete_file(file.id)
session.commit()
- return WorkflowProcessor(workflow_model)
+
+
@staticmethod
def __get_bpmn_workflow(workflow_model: WorkflowModel, spec: WorkflowSpec = None, validate_only=False):
diff --git a/crc/services/workflow_service.py b/crc/services/workflow_service.py
index ecf16131..082e41e5 100755
--- a/crc/services/workflow_service.py
+++ b/crc/services/workflow_service.py
@@ -27,7 +27,7 @@ from crc.models.api_models import Task, MultiInstanceType, WorkflowApi
from crc.models.file import LookupDataModel, FileModel, File, FileSchema
from crc.models.ldap import LdapModel
from crc.models.study import StudyModel
-from crc.models.task_event import TaskEventModel
+from crc.models.task_event import TaskEventModel, TaskAction
from crc.models.user import UserModel
from crc.models.workflow import WorkflowModel, WorkflowStatus
from crc.services.data_store_service import DataStoreBase
@@ -45,11 +45,6 @@ from flask import g
class WorkflowService(object):
- TASK_ACTION_COMPLETE = "COMPLETE"
- TASK_ACTION_TOKEN_RESET = "TOKEN_RESET"
- TASK_ACTION_HARD_RESET = "HARD_RESET"
- TASK_ACTION_SOFT_RESET = "SOFT_RESET"
- TASK_ACTION_ASSIGNMENT = "ASSIGNMENT" # Whenever the lane changes between tasks we assign the task to specifc user.
TASK_STATE_LOCKED = "LOCKED" # When the task belongs to a different user.
@@ -723,7 +718,7 @@ class WorkflowService(object):
query = db.session.query(TaskEventModel) \
.filter_by(workflow_id=workflow_id) \
.filter_by(task_name=spiff_task.task_spec.name) \
- .filter_by(action=WorkflowService.TASK_ACTION_COMPLETE)
+ .filter_by(action=TaskAction.COMPLETE.value)
if hasattr(spiff_task, 'internal_data') and 'runtimes' in spiff_task.internal_data:
query = query.filter_by(mi_index=spiff_task.internal_data['runtimes'])
@@ -987,14 +982,14 @@ class WorkflowService(object):
should be called whenever progress is made on a workflow."""
db.session.query(TaskEventModel). \
filter(TaskEventModel.workflow_id == processor.workflow_model.id). \
- filter(TaskEventModel.action == WorkflowService.TASK_ACTION_ASSIGNMENT).delete()
+ filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).delete()
db.session.commit()
tasks = processor.get_current_user_tasks()
for task in tasks:
user_ids = WorkflowService.get_users_assigned_to_task(processor, task)
for user_id in user_ids:
- WorkflowService.log_task_action(user_id, processor, task, WorkflowService.TASK_ACTION_ASSIGNMENT)
+ WorkflowService.log_task_action(user_id, processor, task, TaskAction.ASSIGNMENT.value)
@staticmethod
def get_users_assigned_to_task(processor, spiff_task) -> List[str]:
@@ -1132,13 +1127,4 @@ class WorkflowService(object):
db.session.commit()
return workflow_model
- @staticmethod
- def delete_workflow_spec_task_events(spec_id):
- session.query(TaskEventModel).filter(TaskEventModel.workflow_spec_id == spec_id).delete()
- session.commit()
-
- @staticmethod
- def delete_workflow_spec_workflow_models(spec_id):
- for workflow in session.query(WorkflowModel).filter_by(workflow_spec_id=spec_id):
- StudyService.delete_workflow(workflow.id)
diff --git a/package-lock.json b/package-lock.json
index 48e341a0..1638e11d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,3 +1,6 @@
{
- "lockfileVersion": 1
+ "name": "cr-connect-workflow",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {}
}
diff --git a/tests/base_test.py b/tests/base_test.py
index 69cd276f..79e4069e 100644
--- a/tests/base_test.py
+++ b/tests/base_test.py
@@ -15,7 +15,7 @@ from flask import g
from crc import app, db, session
from crc.models.api_models import WorkflowApiSchema, MultiInstanceType
from crc.models.file import FileModel, CONTENT_TYPES
-from crc.models.task_event import TaskEventModel
+from crc.models.task_event import TaskEventModel, TaskAction
from crc.models.study import StudyModel, StudyStatus, ProgressStatus
from crc.models.user import UserModel
from crc.models.workflow import WorkflowSpecCategory
@@ -368,7 +368,7 @@ class BaseTest(unittest.TestCase):
task_events = session.query(TaskEventModel) \
.filter_by(workflow_id=workflow.id) \
.filter_by(task_id=task_id) \
- .filter_by(action=WorkflowService.TASK_ACTION_COMPLETE) \
+ .filter_by(action=TaskAction.COMPLETE.value) \
.order_by(TaskEventModel.date.desc()).all()
self.assertGreater(len(task_events), 0)
event = task_events[0]
@@ -377,7 +377,7 @@ class BaseTest(unittest.TestCase):
self.assertEqual(user_uid, event.user_uid)
self.assertEqual(workflow.id, event.workflow_id)
self.assertEqual(workflow.workflow_spec_id, event.workflow_spec_id)
- self.assertEqual(WorkflowService.TASK_ACTION_COMPLETE, event.action)
+ self.assertEqual(TaskAction.COMPLETE.value, event.action)
self.assertEqual(task_in.id, task_id)
self.assertEqual(task_in.name, event.task_name)
self.assertEqual(task_in.title, event.task_title)
diff --git a/tests/data/data_store_set/data_store_set.bpmn b/tests/data/data_store_set/data_store_set.bpmn
index 7f592b8b..045133ee 100644
--- a/tests/data/data_store_set/data_store_set.bpmn
+++ b/tests/data/data_store_set/data_store_set.bpmn
@@ -6,10 +6,10 @@
-
+
Flow_10t9bdk
-
+
@@ -52,7 +52,7 @@ data_store_set(type='file', key=key, value=value, file_id=file_id)
-
+
diff --git a/tests/data/reset_workflow/reset_workflow.bpmn b/tests/data/reset_workflow/reset_workflow.bpmn
index b199cf6c..63efaa72 100644
--- a/tests/data/reset_workflow/reset_workflow.bpmn
+++ b/tests/data/reset_workflow/reset_workflow.bpmn
@@ -1,5 +1,5 @@
-
+
Use this process to reset a workflow for the current study. You must enter the name of the workflow. I.e., lower case with underscores.
@@ -15,7 +15,7 @@
-
+
@@ -28,7 +28,7 @@
SequenceFlow_1q2ton3
SequenceFlow_0x127gc
- value = reset_workflow(workflow_name=workflow_name)
+ value = reset_workflow(workflow_name)
# Reset Workflow
@@ -46,28 +46,28 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
diff --git a/tests/data/start_workflow/start_workflow.bpmn b/tests/data/start_workflow/start_workflow.bpmn
index c0b6ea17..af380b03 100644
--- a/tests/data/start_workflow/start_workflow.bpmn
+++ b/tests/data/start_workflow/start_workflow.bpmn
@@ -1,5 +1,5 @@
-
+
Flow_0ac3s7d
@@ -14,7 +14,7 @@
-
+
diff --git a/tests/files/test_delete_task_data.py b/tests/files/test_delete_task_data.py
index 282ea368..a6dcec41 100644
--- a/tests/files/test_delete_task_data.py
+++ b/tests/files/test_delete_task_data.py
@@ -4,7 +4,7 @@ from crc import session
from crc.models.data_store import DataStoreModel
from crc.models.file import FileModel
-from crc.models.task_event import TaskEventModel
+from crc.models.task_event import TaskEventModel, TaskAction
from crc.services.workflow_service import WorkflowService
from io import BytesIO
@@ -100,7 +100,7 @@ class TestDeleteTaskData(BaseTest):
# Make sure we have something in task_events
task_events = session.query(TaskEventModel).\
filter(TaskEventModel.workflow_id == workflow.id).\
- filter(TaskEventModel.action == WorkflowService.TASK_ACTION_COMPLETE).all()
+ filter(TaskEventModel.action == TaskAction.COMPLETE.value).all()
for task_event in task_events:
self.assertNotEqual({}, task_event.form_data)
@@ -117,7 +117,7 @@ class TestDeleteTaskData(BaseTest):
files = session.query(FileModel).filter(FileModel.workflow_id == workflow.id).all()
task_events = session.query(TaskEventModel).\
filter(TaskEventModel.workflow_id == workflow.id).\
- filter(TaskEventModel.action == WorkflowService.TASK_ACTION_COMPLETE).all()
+ filter(TaskEventModel.action == TaskAction.COMPLETE.value).all()
self.assertEqual(0, len(data_stores))
self.assertEqual(0, len(data_stores_1))
diff --git a/tests/scripts/test_start_workflow.py b/tests/scripts/test_start_workflow.py
index 4ca1ea09..18c0b9fb 100644
--- a/tests/scripts/test_start_workflow.py
+++ b/tests/scripts/test_start_workflow.py
@@ -22,6 +22,7 @@ class TestStartWorkflow(BaseTest):
return workflow
def test_start_workflow_validation(self):
+ random_wf = self.create_workflow('random_fact') # Assure we have a workflow to start.
spec_model = self.load_test_spec('start_workflow')
rv = self.app.get('/v1.0/workflow-specification/%s/validate' % spec_model.id, headers=self.logged_in_headers())
self.assertEqual([], rv.json)
diff --git a/tests/test_data_store_service.py b/tests/test_data_store_service.py
index 1cbdc814..4c4339ed 100644
--- a/tests/test_data_store_service.py
+++ b/tests/test_data_store_service.py
@@ -275,3 +275,16 @@ class TestDataStoreValidation(BaseTest):
self.assertEqual(3, len(result))
for record in result:
self.assertEqual('false', record.value)
+
+ def test_do_not_fail_deleting_record_that_does_not_exist(self):
+ file_id = self.add_test_file()
+
+ workflow = self.create_workflow('data_store_set')
+ workflow_api = self.get_workflow_api(workflow)
+ task = workflow_api.next_task
+
+ # The workflow turns the string 'None' into the value None
+ form_data = {'key': 'my_key', 'value': 'None', 'file_id': file_id}
+ workflow_api = self.complete_form(workflow, task, form_data)
+ task = workflow_api.next_task
+ self.assertEqual('Event_EndEvent', task.name)
diff --git a/tests/test_lookup_service.py b/tests/test_lookup_service.py
index 78440892..025b812f 100644
--- a/tests/test_lookup_service.py
+++ b/tests/test_lookup_service.py
@@ -63,7 +63,8 @@ class TestLookupService(BaseTest):
file.close()
# restart the workflow, so it can pick up the changes.
- processor = WorkflowProcessor.reset(workflow)
+ WorkflowProcessor.reset(workflow)
+ processor = WorkflowProcessor(workflow)
workflow = processor.workflow_model
LookupService.lookup(workflow, "Task_Enum_Lookup", "sponsor", "sam", limit=10)
@@ -100,7 +101,8 @@ class TestLookupService(BaseTest):
results = LookupService.lookup(workflow, task.task_spec.name, "selectedItem", "", value="apples", limit=10)
self.assertEqual(0, len(results), "We shouldn't find our fruits mixed in with our animals.")
- processor = WorkflowProcessor.reset(workflow, clear_data=True)
+ WorkflowProcessor.reset(workflow, clear_data=True)
+ processor = WorkflowProcessor(workflow)
processor.do_engine_steps()
task = processor.get_ready_user_tasks()[0]
task.data = {"type": "fruits"}
diff --git a/tests/test_user_roles.py b/tests/test_user_roles.py
index da24b787..c1e6ed42 100644
--- a/tests/test_user_roles.py
+++ b/tests/test_user_roles.py
@@ -6,7 +6,7 @@ from crc.models.api_models import NavigationItemSchema
from crc.models.workflow import WorkflowStatus
from crc import db
from crc.api.common import ApiError
-from crc.models.task_event import TaskEventModel, TaskEventSchema
+from crc.models.task_event import TaskEventModel, TaskEventSchema, TaskAction
from crc.services.workflow_service import WorkflowService
@@ -82,7 +82,7 @@ class TestUserRoles(BaseTest):
# the supervisor.
task_logs = db.session.query(TaskEventModel). \
filter(TaskEventModel.user_uid == supervisor.uid). \
- filter(TaskEventModel.action == WorkflowService.TASK_ACTION_ASSIGNMENT).all()
+ filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).all()
self.assertEqual(1, len(task_logs))
# A call to the /task endpoint as the supervisor user should return a list of
@@ -213,7 +213,7 @@ class TestUserRoles(BaseTest):
def get_assignment_task_events(self, uid):
return db.session.query(TaskEventModel). \
filter(TaskEventModel.user_uid == uid). \
- filter(TaskEventModel.action == WorkflowService.TASK_ACTION_ASSIGNMENT).all()
+ filter(TaskEventModel.action == TaskAction.ASSIGNMENT.value).all()
def test_workflow_reset_correctly_resets_the_task_events(self):
diff --git a/tests/workflow/test_workflow_processor.py b/tests/workflow/test_workflow_processor.py
index 0fb3a036..db5f8c36 100644
--- a/tests/workflow/test_workflow_processor.py
+++ b/tests/workflow/test_workflow_processor.py
@@ -272,7 +272,8 @@ class TestWorkflowProcessor(BaseTest):
# self.assertFalse(processor2.is_latest_spec) # Still at version 1.
# Do a hard reset, which should bring us back to the beginning, but retain the data.
- processor2 = WorkflowProcessor.reset(processor2.workflow_model)
+ WorkflowProcessor.reset(processor2.workflow_model)
+ processor2 = WorkflowProcessor(processor2.workflow_model)
processor3 = WorkflowProcessor(processor.workflow_model)
processor3.do_engine_steps()
self.assertEqual("Step 1", processor3.next_task().task_spec.description)
diff --git a/tests/workflow/test_workflow_reset.py b/tests/workflow/test_workflow_reset.py
index 01c923be..f81b9108 100644
--- a/tests/workflow/test_workflow_reset.py
+++ b/tests/workflow/test_workflow_reset.py
@@ -23,7 +23,7 @@ class TestWorkflowReset(BaseTest):
second_task = workflow_api.next_task
self.assertEqual('Task_GetAge', second_task.name)
- ResetWorkflow().do_task(second_task, workflow.study_id, workflow.id, reset_id='two_user_tasks')
+ ResetWorkflow().do_task(second_task, workflow.study_id, workflow.id, workflow_spec_id='two_user_tasks')
workflow_api = self.get_workflow_api(workflow)
task = workflow_api.next_task
@@ -43,4 +43,12 @@ class TestWorkflowReset(BaseTest):
first_task = workflow_api.next_task
with self.assertRaises(ApiError):
- ResetWorkflow().do_task(first_task, workflow.study_id, workflow.id, reset_id='bad_workflow_name')
+ ResetWorkflow().do_task(first_task, workflow.study_id, workflow.id, workflow_spec_id='bad_workflow_name')
+
+ def test_workflow_reset_no_start(self):
+ """Sometimes we want to reset the workflow, but not start it up (don't do the engine steps etc...)"""
+ workflow = self.create_workflow('two_user_tasks')
+ workflow_api = self.get_workflow_api(workflow)
+ task = workflow_api.next_task
+
+ ResetWorkflow().do_task(task, workflow.study_id, workflow.id, workflow_spec_id='two_user_tasks')
diff --git a/tests/workflow/test_workflow_restart.py b/tests/workflow/test_workflow_restart.py
index 307acd9b..79477f37 100644
--- a/tests/workflow/test_workflow_restart.py
+++ b/tests/workflow/test_workflow_restart.py
@@ -68,7 +68,7 @@ class TestWorkflowRestart(BaseTest):
self.assertEqual(True, IsFileUploaded.do_task(
IsFileUploaded, first_task, study_id, workflow.id, irb_code))
- workflow_api = self.restart_workflow_api(workflow_api, delete_files=True)
+ workflow_api = self.restart_workflow_api(workflow_api, clear_data=True)
first_task = workflow_api.next_task
# Assert we do not have the file