From 7a14a58518167c94aaddf729e86f493673c55ec6 Mon Sep 17 00:00:00 2001 From: jasquat Date: Thu, 23 Mar 2023 10:44:09 -0400 Subject: [PATCH] commented out reset process code and added comment and raise until we get it actually working and fixed issue with viewing at completed task where it was not including the tasks for the parent bpmn processes --- .../models/bpmn_process.py | 3 + .../models/bpmn_process_definition.py | 3 + .../bpmn_process_definition_relationship.py | 3 + .../models/task_definition.py | 3 + .../routes/process_instances_controller.py | 41 +++- .../services/process_instance_processor.py | 212 +++++++++--------- .../services/task_service.py | 11 + .../services/workflow_execution_service.py | 2 + .../unit/test_process_instance_processor.py | 125 ++++++----- 9 files changed, 234 insertions(+), 169 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py index c38fed7bb..d5ba53dfc 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process.py @@ -1,5 +1,7 @@ from __future__ import annotations +from dataclasses import dataclass + from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship @@ -18,6 +20,7 @@ class BpmnProcessNotFoundError(Exception): # "success", # boolean # "bpmn_messages", # if top-level process # "correlations", # if top-level process +@dataclass class BpmnProcessModel(SpiffworkflowBaseDBModel): __tablename__ = "bpmn_process" id: int = db.Column(db.Integer, primary_key=True) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py index 7f60d7511..902062357 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition.py @@ -1,5 +1,7 @@ from __future__ import annotations +from dataclasses import dataclass + from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel @@ -10,6 +12,7 @@ from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel # # each subprocess will have its own row in this table. # there is a join table to link them together: bpmn_process_definition_relationship +@dataclass class BpmnProcessDefinitionModel(SpiffworkflowBaseDBModel): __tablename__ = "bpmn_process_definition" id: int = db.Column(db.Integer, primary_key=True) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py index 096570d84..51126503a 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/bpmn_process_definition_relationship.py @@ -1,5 +1,7 @@ from __future__ import annotations +from dataclasses import dataclass + from sqlalchemy import ForeignKey from sqlalchemy import UniqueConstraint @@ -10,6 +12,7 @@ from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel +@dataclass class BpmnProcessDefinitionRelationshipModel(SpiffworkflowBaseDBModel): __tablename__ = "bpmn_process_definition_relationship" __table_args__ = ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py index 791e1deab..ec2436493 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/task_definition.py @@ -1,5 +1,7 @@ from __future__ import annotations +from dataclasses import dataclass + from sqlalchemy import ForeignKey from sqlalchemy import UniqueConstraint from sqlalchemy.orm import relationship @@ -11,6 +13,7 @@ from spiffworkflow_backend.models.db import db from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel +@dataclass class TaskDefinitionModel(SpiffworkflowBaseDBModel): __tablename__ = "task_definition" __table_args__ = ( diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py index b0cde36f8..75e2a23cd 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -606,6 +606,8 @@ def process_instance_task_list( TaskModel.process_instance_id == process_instance.id, ) + to_task_model: Optional[TaskModel] = None + task_models_of_parent_bpmn_processes_guids: list[str] = [] if to_task_guid is not None: to_task_model = TaskModel.query.filter_by(guid=to_task_guid, process_instance_id=process_instance.id).first() if to_task_model is None: @@ -614,7 +616,28 @@ def process_instance_task_list( message=f"Cannot find a task with guid '{to_task_guid}' for process instance '{process_instance.id}'", status_code=400, ) - task_model_query = task_model_query.filter(TaskModel.end_in_seconds <= to_task_model.end_in_seconds) + + if to_task_model.state != "COMPLETED": + # TODO: find a better term for viewing at task state + raise ApiError( + error_code="task_cannot_be_viewed_at", + message=( + f"Desired task with guid '{to_task_guid}' for process instance '{process_instance.id}' was never" + " completed and therefore cannot be viewed at." + ), + status_code=400, + ) + + _parent_bpmn_processes, task_models_of_parent_bpmn_processes = ( + TaskService.task_models_of_parent_bpmn_processes(to_task_model) + ) + task_models_of_parent_bpmn_processes_guids = [p.guid for p in task_models_of_parent_bpmn_processes if p.guid] + task_model_query = task_model_query.filter( + or_( + TaskModel.end_in_seconds <= to_task_model.end_in_seconds, # type: ignore + TaskModel.guid.in_(task_models_of_parent_bpmn_processes_guids), # type: ignore + ) + ) bpmn_process_alias = aliased(BpmnProcessModel) direct_parent_bpmn_process_alias = aliased(BpmnProcessModel) @@ -649,6 +672,9 @@ def process_instance_task_list( TaskDefinitionModel.properties_json.label("task_definition_properties_json"), # type: ignore TaskModel.guid, TaskModel.state, + TaskModel.properties_json, + TaskModel.end_in_seconds, + TaskModel.start_in_seconds, ) ) @@ -656,11 +682,18 @@ def process_instance_task_list( task_model_query = task_model_query.filter(bpmn_process_alias.id.in_(bpmn_process_ids)) task_models = task_model_query.all() - if to_task_guid is not None: + if to_task_model is not None: task_models_dict = json.loads(current_app.json.dumps(task_models)) for task_model in task_models_dict: - if task_model["guid"] == to_task_guid and task_model["state"] == "COMPLETED": - task_model["state"] = "READY" + end_in_seconds = float(task_model["end_in_seconds"]) + if to_task_model.guid == task_model["guid"] and task_model["state"] == "COMPLETED": + TaskService.reset_task_model_dict(task_model, state="READY") + elif ( + end_in_seconds is None + or to_task_model.end_in_seconds is None + or to_task_model.end_in_seconds < end_in_seconds + ) and task_model["guid"] in task_models_of_parent_bpmn_processes_guids: + TaskService.reset_task_model_dict(task_model, state="WAITING") return make_response(jsonify(task_models_dict), 200) return make_response(jsonify(task_models), 200) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index 849a0ee54..535a2be41 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -52,8 +52,6 @@ from SpiffWorkflow.spiff.serializer.config import SPIFF_SPEC_CONFIG # type: ign from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState from SpiffWorkflow.util.deep_merge import DeepMerge # type: ignore -from sqlalchemy import and_ -from sqlalchemy import or_ from spiffworkflow_backend.exceptions.api_error import ApiError from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel @@ -1311,114 +1309,118 @@ class ProcessInstanceProcessor: # Saving the workflow seems to reset the status self.suspend() + # FIXME: this currently cannot work for multi-instance tasks and loopback. It can somewhat for not those + # if we can properly handling resetting children tasks. Right now if we set them all to FUTURE then + # they never get picked up by spiff and processed. The process instance just stops after the to_task_guid + # and marks itself complete without processing any of the children. @classmethod def reset_process( cls, process_instance: ProcessInstanceModel, to_task_guid: str, commit: Optional[bool] = False ) -> None: """Reset a process to an earlier state.""" - cls.add_event_to_process_instance( - process_instance, ProcessInstanceEventType.process_instance_rewound_to_task.value, task_guid=to_task_guid - ) - - to_task_model = TaskModel.query.filter_by(guid=to_task_guid, process_instance_id=process_instance.id).first() - if to_task_model is None: - raise TaskNotFoundError( - f"Cannot find a task with guid '{to_task_guid}' for process instance '{process_instance.id}'" - ) - - parent_bpmn_processes, task_models_of_parent_bpmn_processes = TaskService.task_models_of_parent_bpmn_processes( - to_task_model - ) - task_models_of_parent_bpmn_processes_guids = [p.guid for p in task_models_of_parent_bpmn_processes if p.guid] - parent_bpmn_processes_ids = [p.id for p in parent_bpmn_processes] - tasks_to_update_query = db.session.query(TaskModel).filter( - and_( - or_( - TaskModel.end_in_seconds > to_task_model.end_in_seconds, - TaskModel.end_in_seconds.is_(None), # type: ignore - ), - TaskModel.process_instance_id == process_instance.id, - # TaskModel.bpmn_process_id.in_(parent_bpmn_processes_ids), # type: ignore - ) - ) - tasks_to_update = tasks_to_update_query.all() - - # run all queries before making changes to task_model - if commit: - # tasks_to_delete_query = db.session.query(TaskModel).filter( - # and_( - # or_( - # TaskModel.end_in_seconds > to_task_model.end_in_seconds, - # TaskModel.end_in_seconds.is_not(None), # type: ignore - # ), - # TaskModel.process_instance_id == process_instance.id, - # TaskModel.guid.not_in(task_models_of_parent_bpmn_processes_guids), # type: ignore - # TaskModel.bpmn_process_id.not_in(parent_bpmn_processes_ids), # type: ignore - # ) - # ) - # - # tasks_to_delete = tasks_to_delete_query.all() - # - # # delete any later tasks from to_task_model and delete bpmn processes that may be - # # link directly to one of those tasks. - # tasks_to_delete_guids = [t.guid for t in tasks_to_delete] - # tasks_to_delete_ids = [t.id for t in tasks_to_delete] - # bpmn_processes_to_delete = BpmnProcessModel.query.filter( - # BpmnProcessModel.guid.in_(tasks_to_delete_guids) # type: ignore - # ).order_by(BpmnProcessModel.id.desc()).all() - # human_tasks_to_delete = HumanTaskModel.query.filter( - # HumanTaskModel.task_model_id.in_(tasks_to_delete_ids) # type: ignore - # ).all() - # - # - # import pdb; pdb.set_trace() - # # ensure the correct order for foreign keys - # for human_task_to_delete in human_tasks_to_delete: - # db.session.delete(human_task_to_delete) - # db.session.commit() - # for task_to_delete in tasks_to_delete: - # db.session.delete(task_to_delete) - # db.session.commit() - # for bpmn_process_to_delete in bpmn_processes_to_delete: - # db.session.delete(bpmn_process_to_delete) - # db.session.commit() - - - related_human_task = HumanTaskModel.query.filter_by(task_model_id=to_task_model.id).first() - if related_human_task is not None: - db.session.delete(related_human_task) - - tasks_to_update_ids = [t.id for t in tasks_to_update] - human_tasks_to_delete = HumanTaskModel.query.filter( - HumanTaskModel.task_model_id.in_(tasks_to_update_ids) # type: ignore - ).all() - for human_task_to_delete in human_tasks_to_delete: - db.session.delete(human_task_to_delete) - db.session.commit() - - for task_to_update in tasks_to_update: - TaskService.reset_task_model(task_to_update, state="FUTURE", commit=commit) - - parent_task_model = TaskModel.query.filter_by(guid=to_task_model.properties_json["parent"]).first() - if parent_task_model is None: - raise TaskNotFoundError( - f"Cannot find a task with guid '{to_task_guid}' for process instance '{process_instance.id}'" - ) - - TaskService.reset_task_model( - to_task_model, - state="READY", - json_data_hash=parent_task_model.json_data_hash, - python_env_data_hash=parent_task_model.python_env_data_hash, - commit=commit, - ) - for task_model in task_models_of_parent_bpmn_processes: - TaskService.reset_task_model(task_model, state="WAITING", commit=commit) - - if commit: - processor = ProcessInstanceProcessor(process_instance) - processor.save() - processor.suspend() + raise Exception("This feature to reset a process instance to a given task is currently unavaiable") + # cls.add_event_to_process_instance( + # process_instance, ProcessInstanceEventType.process_instance_rewound_to_task.value, task_guid=to_task_guid + # ) + # + # to_task_model = TaskModel.query.filter_by(guid=to_task_guid, process_instance_id=process_instance.id).first() + # if to_task_model is None: + # raise TaskNotFoundError( + # f"Cannot find a task with guid '{to_task_guid}' for process instance '{process_instance.id}'" + # ) + # + # parent_bpmn_processes, task_models_of_parent_bpmn_processes = TaskService.task_models_of_parent_bpmn_processes( + # to_task_model + # ) + # [p.guid for p in task_models_of_parent_bpmn_processes if p.guid] + # [p.id for p in parent_bpmn_processes] + # tasks_to_update_query = db.session.query(TaskModel).filter( + # and_( + # or_( + # TaskModel.end_in_seconds > to_task_model.end_in_seconds, + # TaskModel.end_in_seconds.is_(None), # type: ignore + # ), + # TaskModel.process_instance_id == process_instance.id, + # # TaskModel.bpmn_process_id.in_(parent_bpmn_processes_ids), # type: ignore + # ) + # ) + # tasks_to_update = tasks_to_update_query.all() + # + # # run all queries before making changes to task_model + # if commit: + # # tasks_to_delete_query = db.session.query(TaskModel).filter( + # # and_( + # # or_( + # # TaskModel.end_in_seconds > to_task_model.end_in_seconds, + # # TaskModel.end_in_seconds.is_not(None), # type: ignore + # # ), + # # TaskModel.process_instance_id == process_instance.id, + # # TaskModel.guid.not_in(task_models_of_parent_bpmn_processes_guids), # type: ignore + # # TaskModel.bpmn_process_id.not_in(parent_bpmn_processes_ids), # type: ignore + # # ) + # # ) + # # + # # tasks_to_delete = tasks_to_delete_query.all() + # # + # # # delete any later tasks from to_task_model and delete bpmn processes that may be + # # # link directly to one of those tasks. + # # tasks_to_delete_guids = [t.guid for t in tasks_to_delete] + # # tasks_to_delete_ids = [t.id for t in tasks_to_delete] + # # bpmn_processes_to_delete = BpmnProcessModel.query.filter( + # # BpmnProcessModel.guid.in_(tasks_to_delete_guids) # type: ignore + # # ).order_by(BpmnProcessModel.id.desc()).all() + # # human_tasks_to_delete = HumanTaskModel.query.filter( + # # HumanTaskModel.task_model_id.in_(tasks_to_delete_ids) # type: ignore + # # ).all() + # # + # # + # # import pdb; pdb.set_trace() + # # # ensure the correct order for foreign keys + # # for human_task_to_delete in human_tasks_to_delete: + # # db.session.delete(human_task_to_delete) + # # db.session.commit() + # # for task_to_delete in tasks_to_delete: + # # db.session.delete(task_to_delete) + # # db.session.commit() + # # for bpmn_process_to_delete in bpmn_processes_to_delete: + # # db.session.delete(bpmn_process_to_delete) + # # db.session.commit() + # + # related_human_task = HumanTaskModel.query.filter_by(task_model_id=to_task_model.id).first() + # if related_human_task is not None: + # db.session.delete(related_human_task) + # + # tasks_to_update_ids = [t.id for t in tasks_to_update] + # human_tasks_to_delete = HumanTaskModel.query.filter( + # HumanTaskModel.task_model_id.in_(tasks_to_update_ids) # type: ignore + # ).all() + # for human_task_to_delete in human_tasks_to_delete: + # db.session.delete(human_task_to_delete) + # db.session.commit() + # + # for task_to_update in tasks_to_update: + # TaskService.reset_task_model(task_to_update, state="FUTURE", commit=commit) + # + # parent_task_model = TaskModel.query.filter_by(guid=to_task_model.properties_json["parent"]).first() + # if parent_task_model is None: + # raise TaskNotFoundError( + # f"Cannot find a task with guid '{to_task_guid}' for process instance '{process_instance.id}'" + # ) + # + # TaskService.reset_task_model( + # to_task_model, + # state="READY", + # json_data_hash=parent_task_model.json_data_hash, + # python_env_data_hash=parent_task_model.python_env_data_hash, + # commit=commit, + # ) + # for task_model in task_models_of_parent_bpmn_processes: + # TaskService.reset_task_model(task_model, state="WAITING", commit=commit) + # + # if commit: + # processor = ProcessInstanceProcessor(process_instance) + # processor.save() + # processor.suspend() @staticmethod def get_parser() -> MyCustomParser: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py index f75d955c9..29a456772 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py @@ -332,6 +332,17 @@ class TaskService: return (bpmn_processes + b, [parent_task_model] + t) return (bpmn_processes, task_models) + @classmethod + def reset_task_model_dict( + cls, + task_model: dict, + state: str, + ) -> None: + task_model["state"] = state + task_model["start_in_seconds"] = None + task_model["end_in_seconds"] = None + task_model["properties_json"]["state"] = getattr(TaskState, state) + @classmethod def reset_task_model( cls, diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py index 4d44308b3..b8983f1df 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/workflow_execution_service.py @@ -107,6 +107,8 @@ class TaskModelSavingDelegate(EngineStepDelegate): def after_engine_steps(self, bpmn_process_instance: BpmnWorkflow) -> None: if self._should_update_task_model(): + # TODO: also include children of the last task processed. This may help with task resets + # if we have to set their states to FUTURE. # excludes FUTURE and COMPLETED. the others were required to get PP1 to go to completion. for waiting_spiff_task in bpmn_process_instance.get_tasks( TaskState.WAITING | TaskState.CANCELLED | TaskState.READY | TaskState.MAYBE | TaskState.LIKELY diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py index 9b447f342..9ccda1cbe 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/unit/test_process_instance_processor.py @@ -256,63 +256,60 @@ class TestProcessInstanceProcessor(BaseTest): assert spiff_task is not None assert spiff_task.state == TaskState.COMPLETED - def test_properly_resets_process_to_given_task( - self, - app: Flask, - client: FlaskClient, - with_db_and_bpmn_file_cleanup: None, - with_super_admin_user: UserModel, - ) -> None: - self.create_process_group(client, with_super_admin_user, "test_group", "test_group") - initiator_user = self.find_or_create_user("initiator_user") - finance_user_three = self.find_or_create_user("testuser3") - assert initiator_user.principal is not None - assert finance_user_three.principal is not None - AuthorizationService.import_permissions_from_yaml_file() - - finance_group = GroupModel.query.filter_by(identifier="Finance Team").first() - assert finance_group is not None - - process_model = load_test_spec( - process_model_id="test_group/manual_task_with_subprocesses", - process_model_source_directory="manual_task_with_subprocesses", - ) - process_instance = self.create_process_instance_from_process_model( - process_model=process_model, user=initiator_user - ) - processor = ProcessInstanceProcessor(process_instance) - processor.do_engine_steps(save=True) - assert len(process_instance.active_human_tasks) == 1 - initial_human_task_id = process_instance.active_human_tasks[0].id - - # save again to ensure we go attempt to process the human tasks again - processor.save() - - assert len(process_instance.active_human_tasks) == 1 - assert initial_human_task_id == process_instance.active_human_tasks[0].id - - processor = ProcessInstanceProcessor(process_instance) - human_task_one = process_instance.active_human_tasks[0] - spiff_manual_task = processor.__class__.get_task_by_bpmn_identifier( - human_task_one.task_name, processor.bpmn_process_instance - ) - ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) - - processor.suspend() - ProcessInstanceProcessor.reset_process(process_instance, str(spiff_manual_task.id), commit=True) - - process_instance = ProcessInstanceModel.query.filter_by(id=process_instance.id).first() - processor = ProcessInstanceProcessor(process_instance) - human_task_one = process_instance.active_human_tasks[0] - spiff_manual_task = processor.bpmn_process_instance.get_task(UUID(human_task_one.task_id)) - import pdb; pdb.set_trace() - ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) - import pdb; pdb.set_trace() - human_task_one = process_instance.active_human_tasks[0] - spiff_manual_task = processor.bpmn_process_instance.get_task(UUID(human_task_one.task_id)) - ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) - - import pdb; pdb.set_trace() + # TODO: FIX resetting a process instance to a task + # def test_properly_resets_process_to_given_task( + # self, + # app: Flask, + # client: FlaskClient, + # with_db_and_bpmn_file_cleanup: None, + # with_super_admin_user: UserModel, + # ) -> None: + # self.create_process_group(client, with_super_admin_user, "test_group", "test_group") + # initiator_user = self.find_or_create_user("initiator_user") + # finance_user_three = self.find_or_create_user("testuser3") + # assert initiator_user.principal is not None + # assert finance_user_three.principal is not None + # AuthorizationService.import_permissions_from_yaml_file() + # + # finance_group = GroupModel.query.filter_by(identifier="Finance Team").first() + # assert finance_group is not None + # + # process_model = load_test_spec( + # process_model_id="test_group/manual_task_with_subprocesses", + # process_model_source_directory="manual_task_with_subprocesses", + # ) + # process_instance = self.create_process_instance_from_process_model( + # process_model=process_model, user=initiator_user + # ) + # processor = ProcessInstanceProcessor(process_instance) + # processor.do_engine_steps(save=True) + # assert len(process_instance.active_human_tasks) == 1 + # initial_human_task_id = process_instance.active_human_tasks[0].id + # + # # save again to ensure we go attempt to process the human tasks again + # processor.save() + # + # assert len(process_instance.active_human_tasks) == 1 + # assert initial_human_task_id == process_instance.active_human_tasks[0].id + # + # processor = ProcessInstanceProcessor(process_instance) + # human_task_one = process_instance.active_human_tasks[0] + # spiff_manual_task = processor.__class__.get_task_by_bpmn_identifier( + # human_task_one.task_name, processor.bpmn_process_instance + # ) + # ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) + # + # processor.suspend() + # ProcessInstanceProcessor.reset_process(process_instance, str(spiff_manual_task.id), commit=True) + # + # process_instance = ProcessInstanceModel.query.filter_by(id=process_instance.id).first() + # processor = ProcessInstanceProcessor(process_instance) + # human_task_one = process_instance.active_human_tasks[0] + # spiff_manual_task = processor.bpmn_process_instance.get_task(UUID(human_task_one.task_id)) + # ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) + # human_task_one = process_instance.active_human_tasks[0] + # spiff_manual_task = processor.bpmn_process_instance.get_task(UUID(human_task_one.task_id)) + # ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one) def test_properly_saves_tasks_when_running( self, @@ -374,7 +371,11 @@ class TestProcessInstanceProcessor(BaseTest): } third_data_set = { **second_data_set, - **{"set_in_test_process_to_call_script": 1, "set_in_test_process_to_call_subprocess_subprocess_script": 1, "set_in_test_process_to_call_subprocess_script": 1}, + **{ + "set_in_test_process_to_call_script": 1, + "set_in_test_process_to_call_subprocess_subprocess_script": 1, + "set_in_test_process_to_call_subprocess_script": 1, + }, } fourth_data_set = {**third_data_set, **{"a": 1, "we_move_on": True}} fifth_data_set = {**fourth_data_set, **{"validate_only": False, "set_top_level_process_script_after_gate": 1}} @@ -401,7 +402,10 @@ class TestProcessInstanceProcessor(BaseTest): expected_python_env_data = expected_task_data[expected_task_data_key] - base_failure_message = f"Failed on {bpmn_process_identifier} - {spiff_task_identifier} - task data key {expected_task_data_key}." + base_failure_message = ( + f"Failed on {bpmn_process_identifier} - {spiff_task_identifier} - task data key" + f" {expected_task_data_key}." + ) task_model = TaskModel.query.filter_by(guid=str(spiff_task.id)).first() assert task_model.start_in_seconds is not None @@ -414,7 +418,8 @@ class TestProcessInstanceProcessor(BaseTest): assert task_definition.bpmn_process_definition.bpmn_identifier == bpmn_process_identifier message = ( - f"{base_failure_message} Expected: {sorted(expected_python_env_data)}. Received: {sorted(task_model.json_data())}" + f"{base_failure_message} Expected: {sorted(expected_python_env_data)}. Received:" + f" {sorted(task_model.json_data())}" ) # TODO: if we split out env data again we will need to use it here instead of json_data # assert task_model.python_env_data() == expected_python_env_data, message