diff --git a/spiffworkflow-backend/bin/get_bpmn_json_for_process_instance.py b/spiffworkflow-backend/bin/get_bpmn_json_for_process_instance.py
index fe60de707..406047561 100755
--- a/spiffworkflow-backend/bin/get_bpmn_json_for_process_instance.py
+++ b/spiffworkflow-backend/bin/get_bpmn_json_for_process_instance.py
@@ -6,7 +6,6 @@ from spiffworkflow_backend.services.process_instance_processor import ProcessIns
def main(process_instance_id: str) -> None:
- """Main."""
app = create_app()
with app.app_context():
process_instance = ProcessInstanceModel.query.filter_by(id=process_instance_id).first()
@@ -15,7 +14,9 @@ def main(process_instance_id: str) -> None:
if not process_instance:
raise Exception(f"Could not find a process instance with id: {process_instance_id}")
- processor = ProcessInstanceProcessor(process_instance)
+ processor = ProcessInstanceProcessor(
+ process_instance, include_completed_subprocesses=True, include_task_data_for_completed_tasks=True
+ )
processor.dump_to_disk(file_path)
print(f"Saved to {file_path}")
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 ea3f59b08..03fb640f9 100644
--- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
+++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py
@@ -98,6 +98,7 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelSer
from spiffworkflow_backend.services.service_task_service import CustomServiceTask
from spiffworkflow_backend.services.service_task_service import ServiceTaskDelegate
from spiffworkflow_backend.services.spec_file_service import SpecFileService
+from spiffworkflow_backend.services.task_service import StartAndEndTimes
from spiffworkflow_backend.services.task_service import TaskService
from spiffworkflow_backend.services.user_service import UserService
from spiffworkflow_backend.services.workflow_execution_service import ExecutionStrategy
@@ -521,8 +522,14 @@ class ProcessInstanceProcessor:
bpmn_process_instance = cls._serializer.from_dict(process_copy)
bpmn_process_instance.script_engine = cls._default_script_engine
for spiff_task in bpmn_process_instance.get_tasks():
+ start_and_end_times: StartAndEndTimes | None = None
+ if spiff_task.has_state(TaskState.COMPLETED | TaskState.ERROR):
+ start_and_end_times = {
+ "start_in_seconds": spiff_task.last_state_change,
+ "end_in_seconds": spiff_task.last_state_change,
+ }
task_service.update_task_model_with_spiff_task(
- spiff_task, store_process_instance_events=store_process_instance_events
+ spiff_task, store_process_instance_events=store_process_instance_events, start_and_end_times=start_and_end_times
)
task_service.save_objects_to_database()
db.session.commit()
@@ -1687,8 +1694,8 @@ class ProcessInstanceProcessor:
return [t for t in all_tasks if t.task_spec.manual]
def get_all_completed_tasks(self) -> list[SpiffTask]:
- all_tasks = self.bpmn_process_instance.get_tasks(state=TaskState.ANY_MASK)
- return [t for t in all_tasks if t.task_spec.manual and t.state in [TaskState.COMPLETED, TaskState.CANCELLED]]
+ return_tasks: list[SpiffTask] = self.bpmn_process_instance.get_tasks(state=TaskState.COMPLETED | TaskState.CANCELLED)
+ return return_tasks
def get_all_waiting_tasks(self) -> list[SpiffTask]:
all_tasks = self.bpmn_process_instance.get_tasks(state=TaskState.ANY_MASK)
diff --git a/spiffworkflow-backend/tests/data/service-task-with-data-obj/main.bpmn b/spiffworkflow-backend/tests/data/service-task-with-data-obj/main.bpmn
index c2f1cf629..8cb11f4a7 100644
--- a/spiffworkflow-backend/tests/data/service-task-with-data-obj/main.bpmn
+++ b/spiffworkflow-backend/tests/data/service-task-with-data-obj/main.bpmn
@@ -34,7 +34,8 @@
DataObjectReference_0qfbjfj
- top_level_data_object = "a"
+ top_level_data_object = "a"
+top_level_var = "b"
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 8eca4c8d8..7a7cc7654 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
@@ -918,8 +918,14 @@ class TestProcessInstanceProcessor(BaseTest):
process_model_source_directory="service-task-with-data-obj",
)
process_instance = self.create_process_instance_from_process_model(process_model=process_model)
- processor = ProcessInstanceProcessor(process_instance)
+ processor = ProcessInstanceProcessor(
+ process_instance, include_completed_subprocesses=True, include_task_data_for_completed_tasks=True
+ )
processor.do_engine_steps(save=True)
+ initial_completed_spiff_task = processor.get_all_completed_tasks()[0]
+ initial_completed_task_model = TaskModel.query.filter_by(guid=str(initial_completed_spiff_task.id)).first()
+ assert initial_completed_task_model.start_in_seconds is not None
+ assert initial_completed_task_model.end_in_seconds is not None
bpmn_process_dict_initial = processor.serialize()
@@ -940,12 +946,17 @@ class TestProcessInstanceProcessor(BaseTest):
ProcessInstanceProcessor.persist_bpmn_process_dict(
bpmn_process_dict_initial, process_instance_model=process_instance, bpmn_definition_to_task_definitions_mappings={}
)
- processor = ProcessInstanceProcessor(process_instance)
+ processor = ProcessInstanceProcessor(
+ process_instance, include_completed_subprocesses=True, include_task_data_for_completed_tasks=True
+ )
bpmn_process_dict_after = processor.serialize()
self.round_last_state_change(bpmn_process_dict_after)
self.round_last_state_change(bpmn_process_dict_initial)
assert bpmn_process_dict_after == bpmn_process_dict_initial
+ final_completed_task_model = TaskModel.query.filter_by(guid=str(initial_completed_spiff_task.id)).first()
+ assert final_completed_task_model.start_in_seconds is not None
+ assert final_completed_task_model.end_in_seconds is not None
def test_can_persist_given_bpmn_process_dict_when_loaded_before(
self,
@@ -958,20 +969,31 @@ class TestProcessInstanceProcessor(BaseTest):
process_model_source_directory="service-task-with-data-obj",
)
process_instance = self.create_process_instance_from_process_model(process_model=process_model)
- processor = ProcessInstanceProcessor(process_instance)
+ processor = ProcessInstanceProcessor(
+ process_instance, include_completed_subprocesses=True, include_task_data_for_completed_tasks=True
+ )
processor.do_engine_steps(save=True)
+ initial_completed_spiff_task = processor.get_all_completed_tasks()[0]
+ initial_completed_task_model = TaskModel.query.filter_by(guid=str(initial_completed_spiff_task.id)).first()
+ assert initial_completed_task_model.start_in_seconds is not None
+ assert initial_completed_task_model.end_in_seconds is not None
bpmn_process_dict_initial = processor.serialize()
ProcessInstanceProcessor.persist_bpmn_process_dict(
bpmn_process_dict_initial, process_instance_model=process_instance, bpmn_definition_to_task_definitions_mappings={}
)
- processor = ProcessInstanceProcessor(process_instance)
+ processor = ProcessInstanceProcessor(
+ process_instance, include_completed_subprocesses=True, include_task_data_for_completed_tasks=True
+ )
bpmn_process_dict_after = processor.serialize()
self.round_last_state_change(bpmn_process_dict_after)
self.round_last_state_change(bpmn_process_dict_initial)
assert bpmn_process_dict_after == bpmn_process_dict_initial
+ final_completed_task_model = TaskModel.query.filter_by(guid=str(initial_completed_spiff_task.id)).first()
+ assert final_completed_task_model.start_in_seconds is not None
+ assert final_completed_task_model.end_in_seconds is not None
def test_returns_error_if_spiff_task_and_human_task_are_different(
self,