tasks can be skipped and manually executed w/ burnettk
This commit is contained in:
parent
6a8676281c
commit
77e97d7a57
|
@ -1066,7 +1066,22 @@ class ProcessInstanceProcessor:
|
||||||
db.session.add(bpmn_process_definition_relationship)
|
db.session.add(bpmn_process_definition_relationship)
|
||||||
return bpmn_process_definition
|
return bpmn_process_definition
|
||||||
|
|
||||||
def _add_bpmn_process_definitions(self, bpmn_spec_dict: dict) -> None:
|
def _add_bpmn_process_definitions(self) -> None:
|
||||||
|
"""Adds serialized_bpmn_definition records to the db session.
|
||||||
|
|
||||||
|
Expects the calling method to commit it.
|
||||||
|
"""
|
||||||
|
if self.process_instance_model.bpmn_process_definition_id is not None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# we may have to already process bpmn_defintions if we ever care about the Root task again
|
||||||
|
bpmn_dict = self.serialize()
|
||||||
|
bpmn_dict_keys = ("spec", "subprocess_specs", "serializer_version")
|
||||||
|
bpmn_spec_dict = {}
|
||||||
|
for bpmn_key in bpmn_dict.keys():
|
||||||
|
if bpmn_key in bpmn_dict_keys:
|
||||||
|
bpmn_spec_dict[bpmn_key] = bpmn_dict[bpmn_key]
|
||||||
|
|
||||||
# store only if mappings is currently empty. this also would mean this is a new instance that has never saved before
|
# store only if mappings is currently empty. this also would mean this is a new instance that has never saved before
|
||||||
store_bpmn_definition_mappings = not self.bpmn_definition_to_task_definitions_mappings
|
store_bpmn_definition_mappings = not self.bpmn_definition_to_task_definitions_mappings
|
||||||
bpmn_process_definition_parent = self._store_bpmn_process_definition(
|
bpmn_process_definition_parent = self._store_bpmn_process_definition(
|
||||||
|
@ -1081,27 +1096,6 @@ class ProcessInstanceProcessor:
|
||||||
)
|
)
|
||||||
self.process_instance_model.bpmn_process_definition = bpmn_process_definition_parent
|
self.process_instance_model.bpmn_process_definition = bpmn_process_definition_parent
|
||||||
|
|
||||||
def _add_bpmn_process_defintions(self) -> None:
|
|
||||||
"""Adds serialized_bpmn_definition records to the db session.
|
|
||||||
|
|
||||||
Expects the calling method to commit it.
|
|
||||||
"""
|
|
||||||
if self.process_instance_model.bpmn_process_definition_id is not None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# we may have to already process bpmn_defintions if we ever care about the Root task again
|
|
||||||
bpmn_dict = self.serialize()
|
|
||||||
bpmn_dict_keys = ("spec", "subprocess_specs", "serializer_version")
|
|
||||||
process_instance_data_dict = {}
|
|
||||||
bpmn_spec_dict = {}
|
|
||||||
for bpmn_key in bpmn_dict.keys():
|
|
||||||
if bpmn_key in bpmn_dict_keys:
|
|
||||||
bpmn_spec_dict[bpmn_key] = bpmn_dict[bpmn_key]
|
|
||||||
else:
|
|
||||||
process_instance_data_dict[bpmn_key] = bpmn_dict[bpmn_key]
|
|
||||||
|
|
||||||
self._add_bpmn_process_definitions(bpmn_spec_dict)
|
|
||||||
|
|
||||||
def save(self) -> None:
|
def save(self) -> None:
|
||||||
"""Saves the current state of this processor to the database."""
|
"""Saves the current state of this processor to the database."""
|
||||||
self.process_instance_model.spiff_serializer_version = self.SERIALIZER_VERSION
|
self.process_instance_model.spiff_serializer_version = self.SERIALIZER_VERSION
|
||||||
|
@ -1240,6 +1234,7 @@ class ProcessInstanceProcessor:
|
||||||
|
|
||||||
def manual_complete_task(self, task_id: str, execute: bool) -> None:
|
def manual_complete_task(self, task_id: str, execute: bool) -> None:
|
||||||
"""Mark the task complete optionally executing it."""
|
"""Mark the task complete optionally executing it."""
|
||||||
|
spiff_tasks_updated = {}
|
||||||
spiff_task = self.bpmn_process_instance.get_task(UUID(task_id))
|
spiff_task = self.bpmn_process_instance.get_task(UUID(task_id))
|
||||||
event_type = ProcessInstanceEventType.task_skipped.value
|
event_type = ProcessInstanceEventType.task_skipped.value
|
||||||
if execute:
|
if execute:
|
||||||
|
@ -1253,10 +1248,14 @@ class ProcessInstanceProcessor:
|
||||||
# We have to get to the actual start event
|
# We have to get to the actual start event
|
||||||
for task in self.bpmn_process_instance.get_tasks(workflow=subprocess):
|
for task in self.bpmn_process_instance.get_tasks(workflow=subprocess):
|
||||||
task.complete()
|
task.complete()
|
||||||
|
spiff_tasks_updated[task.id] = task
|
||||||
if isinstance(task.task_spec, StartEvent):
|
if isinstance(task.task_spec, StartEvent):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
spiff_task.complete()
|
spiff_task.complete()
|
||||||
|
spiff_tasks_updated[spiff_task.id] = spiff_task
|
||||||
|
for child in spiff_task.children:
|
||||||
|
spiff_tasks_updated[child.id] = child
|
||||||
event_type = ProcessInstanceEventType.task_executed_manually.value
|
event_type = ProcessInstanceEventType.task_executed_manually.value
|
||||||
else:
|
else:
|
||||||
spiff_logger = logging.getLogger("spiff")
|
spiff_logger = logging.getLogger("spiff")
|
||||||
|
@ -1264,20 +1263,50 @@ class ProcessInstanceProcessor:
|
||||||
spiff_task._set_state(TaskState.COMPLETED)
|
spiff_task._set_state(TaskState.COMPLETED)
|
||||||
for child in spiff_task.children:
|
for child in spiff_task.children:
|
||||||
child.task_spec._update(child)
|
child.task_spec._update(child)
|
||||||
|
spiff_tasks_updated[child.id] = child
|
||||||
spiff_task.workflow.last_task = spiff_task
|
spiff_task.workflow.last_task = spiff_task
|
||||||
|
spiff_tasks_updated[spiff_task.id] = spiff_task
|
||||||
|
|
||||||
if isinstance(spiff_task.task_spec, EndEvent):
|
if isinstance(spiff_task.task_spec, EndEvent):
|
||||||
for task in self.bpmn_process_instance.get_tasks(TaskState.DEFINITE_MASK, workflow=spiff_task.workflow):
|
for task in self.bpmn_process_instance.get_tasks(TaskState.DEFINITE_MASK, workflow=spiff_task.workflow):
|
||||||
task.complete()
|
task.complete()
|
||||||
|
spiff_tasks_updated[task.id] = task
|
||||||
|
|
||||||
# A subworkflow task will become ready when its workflow is complete. Engine steps would normally
|
# A subworkflow task will become ready when its workflow is complete. Engine steps would normally
|
||||||
# then complete it, but we have to do it ourselves here.
|
# then complete it, but we have to do it ourselves here.
|
||||||
for task in self.bpmn_process_instance.get_tasks(TaskState.READY):
|
for task in self.bpmn_process_instance.get_tasks(TaskState.READY):
|
||||||
if isinstance(task.task_spec, SubWorkflowTask):
|
if isinstance(task.task_spec, SubWorkflowTask):
|
||||||
task.complete()
|
task.complete()
|
||||||
|
spiff_tasks_updated[task.id] = task
|
||||||
|
|
||||||
self.increment_spiff_step()
|
self.increment_spiff_step()
|
||||||
self.add_step()
|
self.add_step()
|
||||||
|
|
||||||
|
for updated_spiff_task in spiff_tasks_updated.values():
|
||||||
|
bpmn_process, task_model, new_task_models, new_json_data_dicts = (
|
||||||
|
TaskService.find_or_create_task_model_from_spiff_task(
|
||||||
|
updated_spiff_task,
|
||||||
|
self.process_instance_model,
|
||||||
|
self._serializer,
|
||||||
|
bpmn_definition_to_task_definitions_mappings=self.bpmn_definition_to_task_definitions_mappings,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
bpmn_process_to_use = bpmn_process or task_model.bpmn_process
|
||||||
|
bpmn_process_json_data = TaskService.update_task_data_on_bpmn_process(
|
||||||
|
bpmn_process_to_use, updated_spiff_task.workflow.data
|
||||||
|
)
|
||||||
|
db.session.add(bpmn_process_to_use)
|
||||||
|
json_data_dict_list = TaskService.update_task_model(task_model, updated_spiff_task, self._serializer)
|
||||||
|
for json_data_dict in json_data_dict_list:
|
||||||
|
if json_data_dict is not None:
|
||||||
|
new_json_data_dicts[json_data_dict["hash"]] = json_data_dict
|
||||||
|
if bpmn_process_json_data is not None:
|
||||||
|
new_json_data_dicts[bpmn_process_json_data["hash"]] = bpmn_process_json_data
|
||||||
|
|
||||||
|
new_task_models[task_model.guid] = task_model
|
||||||
|
db.session.bulk_save_objects(new_task_models.values())
|
||||||
|
TaskService.insert_or_update_json_data_records(new_json_data_dicts)
|
||||||
|
|
||||||
self.add_event_to_process_instance(self.process_instance_model, event_type, task_guid=task_id)
|
self.add_event_to_process_instance(self.process_instance_model, event_type, task_guid=task_id)
|
||||||
self.save()
|
self.save()
|
||||||
# Saving the workflow seems to reset the status
|
# Saving the workflow seems to reset the status
|
||||||
|
@ -1582,7 +1611,7 @@ class ProcessInstanceProcessor:
|
||||||
self._script_engine.environment.revise_state_with_task_data(task)
|
self._script_engine.environment.revise_state_with_task_data(task)
|
||||||
return self.spiff_step_details_mapping(task, start, end)
|
return self.spiff_step_details_mapping(task, start, end)
|
||||||
|
|
||||||
self._add_bpmn_process_defintions()
|
self._add_bpmn_process_definitions()
|
||||||
|
|
||||||
step_delegate = StepDetailLoggingDelegate(self.increment_spiff_step, spiff_step_details_mapping_builder)
|
step_delegate = StepDetailLoggingDelegate(self.increment_spiff_step, spiff_step_details_mapping_builder)
|
||||||
task_model_delegate = TaskModelSavingDelegate(
|
task_model_delegate = TaskModelSavingDelegate(
|
||||||
|
|
|
@ -31,6 +31,7 @@ from spiffworkflow_backend.models.process_instance_report import (
|
||||||
from spiffworkflow_backend.models.process_model import NotificationType
|
from spiffworkflow_backend.models.process_model import NotificationType
|
||||||
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
|
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
|
||||||
from spiffworkflow_backend.models.spec_reference import SpecReferenceCache
|
from spiffworkflow_backend.models.spec_reference import SpecReferenceCache
|
||||||
|
from spiffworkflow_backend.models.task import TaskModel # noqa: F401
|
||||||
from spiffworkflow_backend.models.user import UserModel
|
from spiffworkflow_backend.models.user import UserModel
|
||||||
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
from spiffworkflow_backend.services.authorization_service import AuthorizationService
|
||||||
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
from spiffworkflow_backend.services.file_system_service import FileSystemService
|
||||||
|
@ -2694,8 +2695,19 @@ class TestProcessApi(BaseTest):
|
||||||
f"/v1.0/task-complete/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/{task['id']}",
|
f"/v1.0/task-complete/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/{task['id']}",
|
||||||
headers=self.logged_in_headers(with_super_admin_user),
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
content_type="application/json",
|
content_type="application/json",
|
||||||
|
data=json.dumps({"execute": False}),
|
||||||
)
|
)
|
||||||
assert response.json["status"] == "suspended"
|
assert response.json["status"] == "suspended"
|
||||||
|
task_model = TaskModel.query.filter_by(guid=task["id"]).first()
|
||||||
|
assert task_model is not None
|
||||||
|
assert task_model.state == "COMPLETED"
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/v1.0/process-instances/{self.modify_process_identifier_for_path_param(process_model_identifier)}/{process_instance_id}/task-info",
|
||||||
|
headers=self.logged_in_headers(with_super_admin_user),
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert len(response.json) == 1
|
||||||
|
|
||||||
def setup_initial_groups_for_move_tests(self, client: FlaskClient, with_super_admin_user: UserModel) -> None:
|
def setup_initial_groups_for_move_tests(self, client: FlaskClient, with_super_admin_user: UserModel) -> None:
|
||||||
"""Setup_initial_groups_for_move_tests."""
|
"""Setup_initial_groups_for_move_tests."""
|
||||||
|
|
Loading…
Reference in New Issue