From 524434a10ef88e739849e10972dad14a2b9d5558 Mon Sep 17 00:00:00 2001 From: Elizabeth Esswein Date: Thu, 29 Dec 2022 16:34:38 -0500 Subject: [PATCH] allow option to complete single tasks with or without execution --- src/spiffworkflow_backend/api.yml | 2 +- .../routes/process_api_blueprint.py | 18 +++++------ .../services/process_instance_processor.py | 31 +++++++++++++------ 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/spiffworkflow_backend/api.yml b/src/spiffworkflow_backend/api.yml index 2a247863..304fa4e1 100755 --- a/src/spiffworkflow_backend/api.yml +++ b/src/spiffworkflow_backend/api.yml @@ -1565,7 +1565,7 @@ paths: schema: type: string post: - operationId: spiffworkflow_backend.routes.process_api_blueprint.mark_task_complete + operationId: spiffworkflow_backend.routes.process_api_blueprint.manual_complete_task summary: Mark a task complete without executing it tags: - Process Instances diff --git a/src/spiffworkflow_backend/routes/process_api_blueprint.py b/src/spiffworkflow_backend/routes/process_api_blueprint.py index b8db2dab..2b1f1306 100644 --- a/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -28,11 +28,6 @@ from lxml import etree # type: ignore from lxml.builder import ElementMaker # type: ignore from SpiffWorkflow.task import Task as SpiffTask # type: ignore from SpiffWorkflow.task import TaskState -from sqlalchemy import and_ -from sqlalchemy import asc -from sqlalchemy import desc -from sqlalchemy import or_ - from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( ProcessEntityNotFoundError, ) @@ -99,6 +94,10 @@ from spiffworkflow_backend.services.secret_service import SecretService from spiffworkflow_backend.services.service_task_service import ServiceTaskService from spiffworkflow_backend.services.spec_file_service import SpecFileService from spiffworkflow_backend.services.user_service import UserService +from sqlalchemy import and_ +from sqlalchemy import asc +from sqlalchemy import desc +from sqlalchemy import or_ class TaskDataSelectOption(TypedDict): @@ -2189,23 +2188,24 @@ def send_bpmn_event( ) -def mark_task_complete( +def manual_complete_task( modified_process_model_identifier: str, process_instance_id: str, task_id: str, body: Dict, ) -> Response: """Mark a task complete without executing it.""" + execute = body.get("execute", True) process_instance = ProcessInstanceModel.query.filter( ProcessInstanceModel.id == int(process_instance_id) ).first() if process_instance: processor = ProcessInstanceProcessor(process_instance) - processor.mark_task_complete(task_id) + processor.manual_complete_task(task_id, execute) else: raise ApiError( - error_code="send_bpmn_event_error", - message=f"Could not skip Task {task_id} in Instance {process_instance_id}", + error_code="complete_task", + message=f"Could not complete Task {task_id} in Instance {process_instance_id}", ) return Response( json.dumps(ProcessInstanceModelSchema().dump(process_instance)), diff --git a/src/spiffworkflow_backend/services/process_instance_processor.py b/src/spiffworkflow_backend/services/process_instance_processor.py index 79de71f0..cd838d79 100644 --- a/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/src/spiffworkflow_backend/services/process_instance_processor.py @@ -621,7 +621,7 @@ class ProcessInstanceProcessor: db.session.add(pim) db.session.commit() - def save(self) -> None: + def _save(self) -> None: """Saves the current state of this processor to the database.""" self.process_instance_model.bpmn_json = self.serialize() @@ -643,6 +643,9 @@ class ProcessInstanceProcessor: db.session.add(self.process_instance_model) db.session.commit() + def save(self) -> None: + """Saves the current state and moves on to the next state.""" + self._save() human_tasks = HumanTaskModel.query.filter_by( process_instance_id=self.process_instance_model.id ).all() @@ -729,17 +732,25 @@ class ProcessInstanceProcessor: self.bpmn_process_instance.catch(event_definition) self.do_engine_steps(save=True) - def mark_task_complete(self, task_id: str) -> None: - """Mark the task complete without executing it.""" + def manual_complete_task(self, task_id: str, execute: bool) -> None: + """Mark the task complete optionally executing it.""" spiff_task = self.bpmn_process_instance.get_task(UUID(task_id)) - spiff_task._set_state(TaskState.COMPLETED) + if execute: + current_app.logger.info( + f"Manually executing Task {spiff_task.task_spec.name} of process instance {self.process_instance_model.id}" + ) + spiff_task.complete() + else: + current_app.logger.info( + f"Skipping Task {spiff_task.task_spec.name} of process instance {self.process_instance_model.id}" + ) + spiff_task._set_state(TaskState.COMPLETED) + for child in spiff_task.children: + child.task_spec._update(child) self.bpmn_process_instance.last_task = spiff_task - for child in spiff_task.children: - child.task_spec._update(child) - current_app.logger.info( - f"Task {spiff_task.task_spec.name} of process instance {self.process_instance_model.id} skipped" - ) - self.do_engine_steps(save=True) + self._save() + # Saving the workflow seems to reset the status + self.suspend() @staticmethod def get_parser() -> MyCustomParser: