Squashed 'spiffworkflow-backend/' changes from 1e338f955..153061d41
153061d41 Merge branch 'main' of github.com:sartography/spiffworkflow-backend into main 3724ef7f9 Assure that the Active Task Users table is cleared out before deleting the Active Task Record. We were depending on a cascade here, which seems to fail randomly -- apparently due to some sort of race condition. 137ebbc4b Merge branch 'main' of github.com:sartography/spiffworkflow-backend f8f38f813 pyl - prettier maybe? 02fe90969 Merge branch 'main' into feature/edit-task-data ca7d7d9b3 Merge branch 'main' into feature/edit-task-data c38efe2bd w/Jon Api endpoint to update task data 15b99bf90 mypy git-subtree-dir: spiffworkflow-backend git-subtree-split: 153061d413afc5d7ed0c9cec25b292393585f757
This commit is contained in:
parent
eff49e1ddb
commit
999e0f4d2b
|
@ -469,6 +469,33 @@ paths:
|
|||
items:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-instances/{process_instance_id}/task/{task_id}/update:
|
||||
parameters:
|
||||
- name: process_instance_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of the process instance
|
||||
schema:
|
||||
type: string
|
||||
- name: task_id
|
||||
in: path
|
||||
required: true
|
||||
description: The unique id of the task
|
||||
schema:
|
||||
type: string
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.update_task_data
|
||||
summary: Update the task data for requested instance and task
|
||||
tags:
|
||||
- Process Instances
|
||||
responses:
|
||||
"200":
|
||||
description: Task Updated Successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Workflow"
|
||||
|
||||
/process-models/{process_group_id}/{process_model_id}/script-unit-tests:
|
||||
parameters:
|
||||
- name: process_group_id
|
||||
|
|
|
@ -1493,3 +1493,44 @@ def _update_form_schema_with_task_data_as_needed(
|
|||
for o in value:
|
||||
if isinstance(o, dict):
|
||||
_update_form_schema_with_task_data_as_needed(o, task_data)
|
||||
|
||||
|
||||
def update_task_data(process_instance_id: str, task_id: str, body: Dict) -> Response:
|
||||
"""Update task data."""
|
||||
process_instance = ProcessInstanceModel.query.filter(
|
||||
ProcessInstanceModel.id == int(process_instance_id)
|
||||
).first()
|
||||
if process_instance:
|
||||
process_instance_bpmn_json_dict = json.loads(process_instance.bpmn_json)
|
||||
if "new_task_data" in body:
|
||||
new_task_data_str: str = body["new_task_data"]
|
||||
new_task_data_dict = json.loads(new_task_data_str)
|
||||
if task_id in process_instance_bpmn_json_dict["tasks"]:
|
||||
process_instance_bpmn_json_dict["tasks"][task_id][
|
||||
"data"
|
||||
] = new_task_data_dict
|
||||
process_instance.bpmn_json = json.dumps(process_instance_bpmn_json_dict)
|
||||
db.session.add(process_instance)
|
||||
try:
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
raise ApiError(
|
||||
error_code="update_task_data_error",
|
||||
message=f"Could not update the Instance. Original error is {e}",
|
||||
) from e
|
||||
else:
|
||||
raise ApiError(
|
||||
error_code="update_task_data_error",
|
||||
message=f"Could not find Task: {task_id} in Instance: {process_instance_id}.",
|
||||
)
|
||||
else:
|
||||
raise ApiError(
|
||||
error_code="update_task_data_error",
|
||||
message=f"Could not update task data for Instance: {process_instance_id}, and Task: {task_id}.",
|
||||
)
|
||||
return Response(
|
||||
json.dumps(ProcessInstanceModelSchema().dump(process_instance)),
|
||||
status=200,
|
||||
mimetype="application/json",
|
||||
)
|
||||
|
|
|
@ -522,6 +522,10 @@ class ProcessInstanceProcessor:
|
|||
).all()
|
||||
if len(active_tasks) > 0:
|
||||
for at in active_tasks:
|
||||
active_task_users = at.active_task_users
|
||||
for atu in active_task_users:
|
||||
# don't trust sqlalchemy to cascade - ran into race condition here.
|
||||
db.session.delete(atu)
|
||||
db.session.delete(at)
|
||||
|
||||
db.session.add(self.process_instance_model)
|
||||
|
|
|
@ -55,7 +55,7 @@ class SecretService:
|
|||
def get_secret(key: str) -> SecretModel:
|
||||
"""Get_secret."""
|
||||
secret = db.session.query(SecretModel).filter(SecretModel.key == key).first()
|
||||
if secret is not None:
|
||||
if isinstance(secret, SecretModel):
|
||||
return secret
|
||||
else:
|
||||
raise ApiError(
|
||||
|
|
|
@ -264,7 +264,7 @@ class UserService:
|
|||
.filter(PrincipalModel.user_id == user_id)
|
||||
.first()
|
||||
)
|
||||
if principal:
|
||||
if isinstance(principal, PrincipalModel):
|
||||
return principal
|
||||
raise ApiError(
|
||||
error_code="no_principal_found",
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
"""Process Model."""
|
||||
from decimal import Decimal
|
||||
|
||||
from flask.app import Flask
|
||||
from flask_bpmn.models.db import db
|
||||
|
||||
from spiffworkflow_backend.models.active_task import ActiveTaskModel
|
||||
from spiffworkflow_backend.models.active_task_user import ActiveTaskUserModel
|
||||
from spiffworkflow_backend.services.process_instance_processor import ProcessInstanceProcessor
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
from spiffworkflow_backend.models.spiff_logging import SpiffLoggingModel
|
||||
|
||||
|
||||
class TestActiveTask(BaseTest):
|
||||
|
||||
def test_can_create_and_delete_an_active_task (
|
||||
self, app: Flask, with_db_and_bpmn_file_cleanup: None
|
||||
) -> None:
|
||||
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
|
||||
)
|
||||
active_task = ActiveTaskModel(
|
||||
process_instance_id=process_instance.id,
|
||||
process_model_display_name="my shorts",
|
||||
form_file_name="my_file_name",
|
||||
ui_form_file_name="",
|
||||
task_id="1234",
|
||||
task_name="any old thing",
|
||||
task_title="",
|
||||
task_type="test type",
|
||||
task_status="WAITING",
|
||||
lane_assignment_id=None,
|
||||
)
|
||||
initiator_user = self.find_or_create_user("initiator_user")
|
||||
db.session.add(active_task)
|
||||
db.session.commit()
|
||||
active_task_user = ActiveTaskUserModel(active_task_id=active_task.id, user_id=initiator_user.id)
|
||||
db.session.add(active_task_user)
|
||||
db.session.commit()
|
||||
processor = ProcessInstanceProcessor(process_instance)
|
||||
processor.save() # This should clear out all active tasks and active task users.
|
||||
assert(len(db.session.query(ActiveTaskModel).all()) == 0)
|
Loading…
Reference in New Issue