From 6eef611095dc03cdba841209dc114aa304104b25 Mon Sep 17 00:00:00 2001 From: jasquat Date: Mon, 12 Sep 2022 14:17:18 -0400 Subject: [PATCH] fix call activities to get the form from the process called and added tests to ensure they are working w/ burnettk --- .../routes/process_api_blueprint.py | 24 ++++++- .../services/process_instance_processor.py | 62 +++++++++++-------- .../services/process_model_service.py | 21 ++++++- .../call_activity_nested_duplicate.bpmn | 0 .../call_activity_test.bpmn | 39 ++++++++++++ .../callable_process.bpmn | 26 ++++++++ .../unit/test_process_model.py | 24 ++++++- .../unit/test_spec_file_service.py | 2 +- 8 files changed, 165 insertions(+), 33 deletions(-) rename tests/data/{call_activity_nested => call_activity_duplicate}/call_activity_nested_duplicate.bpmn (100%) create mode 100644 tests/data/call_activity_same_directory/call_activity_test.bpmn create mode 100644 tests/data/call_activity_same_directory/callable_process.bpmn diff --git a/src/spiffworkflow_backend/routes/process_api_blueprint.py b/src/spiffworkflow_backend/routes/process_api_blueprint.py index 561c5436..664e44c0 100644 --- a/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -1,5 +1,6 @@ """APIs for dealing with process groups, process models, and process instances.""" import json +import os import uuid from typing import Any from typing import Dict @@ -44,6 +45,7 @@ from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel from spiffworkflow_backend.services.error_handling_service import ErrorHandlingService +from spiffworkflow_backend.services.file_system_service import FileSystemService from spiffworkflow_backend.services.message_service import MessageService from spiffworkflow_backend.services.process_instance_processor import ( ProcessInstanceProcessor, @@ -773,9 +775,25 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response form_ui_schema_file_name = properties["formUiSchemaFilename"] task = ProcessInstanceService.spiff_task_to_api_task(spiff_task) task.data = spiff_task.data - task.process_name = process_model.id task.process_model_display_name = process_model.display_name + process_model_with_form = process_model + if task.process_name != process_model.primary_process_id: + bpmn_file_full_path = ( + ProcessInstanceProcessor.bpmn_file_full_path_from_bpmn_process_identifier( + task.process_name + ) + ) + relative_path = os.path.relpath( + bpmn_file_full_path, start=FileSystemService.root_path() + ) + process_model_relative_path = os.path.dirname(relative_path) + process_model_with_form = ( + ProcessModelService.get_process_model_from_relative_path( + process_model_relative_path + ) + ) + if task.type == "UserTask": if not form_schema_file_name: raise ( @@ -789,7 +807,7 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response form_contents = prepare_form_data( form_schema_file_name, task.data, - process_model, + process_model_with_form, ) if form_contents: @@ -799,7 +817,7 @@ def task_show(process_instance_id: int, task_id: str) -> flask.wrappers.Response ui_form_contents = prepare_form_data( form_ui_schema_file_name, task.data, - process_model, + process_model_with_form, ) if ui_form_contents: task.form_ui_schema = ui_form_contents diff --git a/src/spiffworkflow_backend/services/process_instance_processor.py b/src/spiffworkflow_backend/services/process_instance_processor.py index 08c984d7..a69e7a81 100644 --- a/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/src/spiffworkflow_backend/services/process_instance_processor.py @@ -462,7 +462,7 @@ class ProcessInstanceProcessor: @staticmethod def backfill_missing_bpmn_process_id_lookup_records( - bpmn_process_identifier: None, + bpmn_process_identifier: str, ) -> Optional[str]: """Backfill_missing_bpmn_process_id_lookup_records.""" process_models = ProcessModelService().get_process_models() @@ -494,6 +494,34 @@ class ProcessInstanceProcessor: ) return None + @staticmethod + def bpmn_file_full_path_from_bpmn_process_identifier( + bpmn_process_identifier: str, + ) -> str: + """Bpmn_file_full_path_from_bpmn_process_identifier.""" + bpmn_process_id_lookup = BpmnProcessIdLookup.query.filter_by( + bpmn_process_identifier=bpmn_process_identifier + ).first() + bpmn_file_full_path = None + if bpmn_process_id_lookup is None: + bpmn_file_full_path = ProcessInstanceProcessor.backfill_missing_bpmn_process_id_lookup_records( + bpmn_process_identifier + ) + else: + bpmn_file_full_path = os.path.join( + FileSystemService.root_path(), + bpmn_process_id_lookup.bpmn_file_relative_path, + ) + if bpmn_file_full_path is None: + raise ( + ApiError( + code="could_not_find_bpmn_process_identifier", + message="Could not find the the given bpmn process identifier from any sources: %s" + % bpmn_process_identifier, + ) + ) + return os.path.abspath(bpmn_file_full_path) + @staticmethod def update_spiff_parser_with_all_process_dependency_files( parser: BpmnDmnParser, @@ -504,7 +532,7 @@ class ProcessInstanceProcessor: processed_identifiers = set() processor_dependencies = parser.get_process_dependencies() processor_dependencies_new = processor_dependencies - processed_identifiers - bpmn_process_identifiers_in_parser = parser.find_all_specs().keys() + bpmn_process_identifiers_in_parser = parser.get_process_ids() new_bpmn_files = set() for bpmn_process_identifier in processor_dependencies_new: @@ -513,28 +541,9 @@ class ProcessInstanceProcessor: if bpmn_process_identifier in bpmn_process_identifiers_in_parser: continue - bpmn_process_id_lookup = BpmnProcessIdLookup.query.filter_by( - bpmn_process_identifier=bpmn_process_identifier - ).first() - new_bpmn_file_full_path = None - if bpmn_process_id_lookup is None: - new_bpmn_file_full_path = ProcessInstanceProcessor.backfill_missing_bpmn_process_id_lookup_records( - bpmn_process_identifier - ) - else: - new_bpmn_file_full_path = os.path.join( - FileSystemService.root_path(), - bpmn_process_id_lookup.bpmn_file_relative_path, - ) - if new_bpmn_file_full_path is None: - raise ( - ApiError( - code="could_not_find_bpmn_process_identifier", - message="Could not find the the given bpmn process identifier from any sources: %s" - % bpmn_process_identifier, - ) - ) - + new_bpmn_file_full_path = ProcessInstanceProcessor.bpmn_file_full_path_from_bpmn_process_identifier( + bpmn_process_identifier + ) new_bpmn_files.add(new_bpmn_file_full_path) processed_identifiers.add(bpmn_process_identifier) @@ -739,7 +748,7 @@ class ProcessInstanceProcessor: db.session.commit() - def do_engine_steps(self, exit_at: None = None) -> None: + def do_engine_steps(self, exit_at: None = None, save: bool = False) -> None: """Do_engine_steps.""" try: self.bpmn_process_instance.refresh_waiting_tasks() @@ -747,6 +756,9 @@ class ProcessInstanceProcessor: self.process_bpmn_messages() self.queue_waiting_receive_messages() + if save: + self.save() + except WorkflowTaskExecException as we: raise ApiError.from_workflow_exception("task_error", str(we), we) from we diff --git a/src/spiffworkflow_backend/services/process_model_service.py b/src/spiffworkflow_backend/services/process_model_service.py index 5cc42a88..01947c69 100644 --- a/src/spiffworkflow_backend/services/process_model_service.py +++ b/src/spiffworkflow_backend/services/process_model_service.py @@ -102,6 +102,16 @@ class ProcessModelService(FileSystemService): return self.__scan_spec(path, FileSystemService.MASTER_SPECIFICATION) return None + @classmethod + def get_process_model_from_relative_path( + cls, relative_path: str + ) -> ProcessModelInfo: + """Get_process_model_from_relative_path.""" + process_group_identifier = os.path.dirname(relative_path) + process_group = cls().get_process_group(process_group_identifier) + path = os.path.join(FileSystemService.root_path(), relative_path) + return cls().__scan_spec(path, process_group=process_group) + def get_process_model( self, process_model_id: str, group_id: Optional[str] = None ) -> ProcessModelInfo: @@ -268,7 +278,10 @@ class ProcessModelService(FileSystemService): return process_group def __scan_spec( - self, path: str, name: str, process_group: Optional[ProcessGroup] = None + self, + path: str, + name: Optional[str] = None, + process_group: Optional[ProcessGroup] = None, ) -> ProcessModelInfo: """__scan_spec.""" spec_path = os.path.join(path, self.WF_JSON_FILE) @@ -284,6 +297,12 @@ class ProcessModelService(FileSystemService): message=f"We could not load the process_model from disk with data: {data}", ) else: + if name is None: + raise ApiError( + code="missing_name_of_process_model", + message="Missing name of process model. It should be given", + ) + spec = ProcessModelInfo( id=name, library=False, diff --git a/tests/data/call_activity_nested/call_activity_nested_duplicate.bpmn b/tests/data/call_activity_duplicate/call_activity_nested_duplicate.bpmn similarity index 100% rename from tests/data/call_activity_nested/call_activity_nested_duplicate.bpmn rename to tests/data/call_activity_duplicate/call_activity_nested_duplicate.bpmn diff --git a/tests/data/call_activity_same_directory/call_activity_test.bpmn b/tests/data/call_activity_same_directory/call_activity_test.bpmn new file mode 100644 index 00000000..e193921d --- /dev/null +++ b/tests/data/call_activity_same_directory/call_activity_test.bpmn @@ -0,0 +1,39 @@ + + + + + Flow_1rcteeq + + + + Flow_1rcteeq + Flow_1rid3w7 + + + Flow_1rid3w7 + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/data/call_activity_same_directory/callable_process.bpmn b/tests/data/call_activity_same_directory/callable_process.bpmn new file mode 100644 index 00000000..7eb4f3d0 --- /dev/null +++ b/tests/data/call_activity_same_directory/callable_process.bpmn @@ -0,0 +1,26 @@ + + + + + Flow_0ogjqo9 + + + Flow_0ogjqo9 + + + + + + + + + + + + + + + + + + diff --git a/tests/spiffworkflow_backend/unit/test_process_model.py b/tests/spiffworkflow_backend/unit/test_process_model.py index 266c43d1..fe3affd2 100644 --- a/tests/spiffworkflow_backend/unit/test_process_model.py +++ b/tests/spiffworkflow_backend/unit/test_process_model.py @@ -22,7 +22,23 @@ class TestProcessModel(BaseTest): assert process_model_one.files == [] assert process_model_one.libraries == [] - def test_can_run_process_model_with_call_activities( + def test_can_run_process_model_with_call_activities_when_in_same_process_model_directory( + self, app: Flask, with_db_and_bpmn_file_cleanup: None + ) -> None: + """Test_can_run_process_model_with_call_activities.""" + process_model = load_test_spec( + "call_activity_test", + process_model_source_directory="call_activity_same_directory", + ) + + process_instance = self.create_process_instance_from_process_model( + process_model + ) + processor = ProcessInstanceProcessor(process_instance) + processor.do_engine_steps(save=True) + assert process_instance.status == "complete" + + def test_can_run_process_model_with_call_activities_when_not_in_same_directory( self, app: Flask, with_db_and_bpmn_file_cleanup: None ) -> None: """Test_can_run_process_model_with_call_activities.""" @@ -47,7 +63,8 @@ class TestProcessModel(BaseTest): process_model ) processor = ProcessInstanceProcessor(process_instance) - processor.do_engine_steps() + processor.do_engine_steps(save=True) + assert process_instance.status == "complete" def test_can_run_process_model_with_call_activities_when_process_identifier_is_not_in_database( self, app: Flask, with_db_and_bpmn_file_cleanup: None @@ -78,7 +95,8 @@ class TestProcessModel(BaseTest): # process model when running the process db.session.query(BpmnProcessIdLookup).delete() processor = ProcessInstanceProcessor(process_instance) - processor.do_engine_steps() + processor.do_engine_steps(save=True) + assert process_instance.status == "complete" def create_test_process_model(self, id: str, display_name: str) -> ProcessModelInfo: """Create_test_process_model.""" diff --git a/tests/spiffworkflow_backend/unit/test_spec_file_service.py b/tests/spiffworkflow_backend/unit/test_spec_file_service.py index 95321c50..fd882e71 100644 --- a/tests/spiffworkflow_backend/unit/test_spec_file_service.py +++ b/tests/spiffworkflow_backend/unit/test_spec_file_service.py @@ -58,7 +58,7 @@ class TestSpecFileService(BaseTest): with pytest.raises(ApiError) as exception: load_test_spec( "call_activity_nested_duplicate", - process_model_source_directory="call_activity_nested", + process_model_source_directory="call_activity_duplicate", bpmn_file_name="call_activity_nested_duplicate", ) assert f"Process id ({bpmn_process_identifier}) has already been used" in str(