From 51642ccd96a4888c919197341949035184571f3f Mon Sep 17 00:00:00 2001 From: jasquat <2487833+jasquat@users.noreply.github.com> Date: Thu, 27 Jul 2023 11:43:53 -0400 Subject: [PATCH] do not display instructions for end events at the top level of the process w/ burnettk (#414) Co-authored-by: jasquat --- .../routes/tasks_controller.py | 39 ++++++++++++------- .../services/process_instance_processor.py | 5 +-- .../services/task_service.py | 11 ++++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py index 68e8e9c94..b9aa42674 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/tasks_controller.py @@ -445,21 +445,27 @@ def _interstitial_stream( tasks = get_reportable_tasks() while True: for spiff_task in tasks: - try: - instructions = render_instructions(spiff_task) - except Exception as e: - api_error = ApiError( - error_code="engine_steps_error", - message=f"Failed to complete an automated task. Error was: {str(e)}", - status_code=400, + # ignore the instructions if they are on the EndEvent for the top level process + if not TaskService.is_main_process_end_event(spiff_task): + print( + "TaskService.get_task_type_from_spiff_task:" + f" {TaskService.get_task_type_from_spiff_task(spiff_task)}" ) - yield _render_data("error", api_error) - raise e - if instructions and spiff_task.id not in reported_ids: - task = ProcessInstanceService.spiff_task_to_api_task(processor, spiff_task) - task.properties = {"instructionsForEndUser": instructions} - yield _render_data("task", task) - reported_ids.append(spiff_task.id) + try: + instructions = render_instructions(spiff_task) + except Exception as e: + api_error = ApiError( + error_code="engine_steps_error", + message=f"Failed to complete an automated task. Error was: {str(e)}", + status_code=400, + ) + yield _render_data("error", api_error) + raise e + if instructions and spiff_task.id not in reported_ids: + task = ProcessInstanceService.spiff_task_to_api_task(processor, spiff_task) + task.properties = {"instructionsForEndUser": instructions} + yield _render_data("task", task) + reported_ids.append(spiff_task.id) if spiff_task.state == TaskState.READY: # do not do any processing if the instance is not currently active if process_instance.status not in ProcessInstanceModel.active_statuses(): @@ -467,6 +473,8 @@ def _interstitial_stream( return if execute_tasks: try: + # run_until_user_message does not run tasks with instructions to use one_at_a_time + # to force it to run the task. processor.do_engine_steps(execution_strategy_name="one_at_a_time") processor.do_engine_steps(execution_strategy_name="run_until_user_message") processor.save() # Fixme - maybe find a way not to do this on every loop? @@ -479,6 +487,9 @@ def _interstitial_stream( yield _render_data("error", api_error) ErrorHandlingService.handle_error(process_instance, wfe) return + # return if process instance is now complete and let the frontend redirect to show page + if process_instance.status not in ProcessInstanceModel.active_statuses(): + return # path used by the interstitial page while executing tasks - ie the background processor is not executing them ready_engine_task_count = _get_ready_engine_step_count(processor.bpmn_process_instance) 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 956f406cf..9ca37e327 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -1477,10 +1477,7 @@ class ProcessInstanceProcessor: if self.bpmn_process_instance.is_completed(): for spiff_task in SpiffTask.Iterator(self.bpmn_process_instance.task_tree, TaskState.ANY_MASK): # Assure that we find the end event for this process_instance, and not for any sub-process_instances. - if ( - spiff_task.task_spec.__class__.__name__ == "EndEvent" - and spiff_task.workflow == self.bpmn_process_instance - ): + if TaskService.is_main_process_end_event(spiff_task): endtasks.append(spiff_task) if len(endtasks) > 0: return endtasks[-1] diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py index aa3dfdd21..b20e35a77 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/task_service.py @@ -613,6 +613,17 @@ class TaskService: ) return task_draft_data + @classmethod + def get_task_type_from_spiff_task(cls, spiff_task: SpiffTask) -> str: + # wrap in str so mypy doesn't lose its mind + return str(spiff_task.task_spec.__class__.__name__) + + @classmethod + def is_main_process_end_event(cls, spiff_task: SpiffTask) -> bool: + return ( + cls.get_task_type_from_spiff_task(spiff_task) == "EndEvent" and spiff_task.workflow.parent_workflow is None + ) + @classmethod def bpmn_process_for_called_activity_or_top_level_process(cls, task_model: TaskModel) -> BpmnProcessModel: """Returns either the bpmn process for the call activity calling the process or the top level bpmn process.