mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-01-13 02:54:27 +00:00
cleaned up using system filters with user_group_identifier so the query no longer raises w/ burnettk
This commit is contained in:
parent
063c5faa8f
commit
cd5c4f26f0
@ -18,13 +18,13 @@ def setup_database_uri(app: Flask) -> None:
|
|||||||
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None:
|
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_URI") is None:
|
||||||
database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}"
|
database_name = f"spiffworkflow_backend_{app.config['ENV_IDENTIFIER']}"
|
||||||
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "sqlite":
|
if app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "sqlite":
|
||||||
app.config[
|
app.config["SQLALCHEMY_DATABASE_URI"] = (
|
||||||
"SQLALCHEMY_DATABASE_URI"
|
f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3"
|
||||||
] = f"sqlite:///{app.instance_path}/db_{app.config['ENV_IDENTIFIER']}.sqlite3"
|
)
|
||||||
elif app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "postgres":
|
elif app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_TYPE") == "postgres":
|
||||||
app.config[
|
app.config["SQLALCHEMY_DATABASE_URI"] = (
|
||||||
"SQLALCHEMY_DATABASE_URI"
|
f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}"
|
||||||
] = f"postgresql://spiffworkflow_backend:spiffworkflow_backend@localhost:5432/{database_name}"
|
)
|
||||||
else:
|
else:
|
||||||
# use pswd to trick flake8 with hardcoded passwords
|
# use pswd to trick flake8 with hardcoded passwords
|
||||||
db_pswd = app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_PASSWORD")
|
db_pswd = app.config.get("SPIFFWORKFLOW_BACKEND_DATABASE_PASSWORD")
|
||||||
|
@ -129,9 +129,9 @@ class ProcessInstanceModel(SpiffworkflowBaseDBModel):
|
|||||||
def serialized_with_metadata(self) -> dict[str, Any]:
|
def serialized_with_metadata(self) -> dict[str, Any]:
|
||||||
process_instance_attributes = self.serialized
|
process_instance_attributes = self.serialized
|
||||||
process_instance_attributes["process_metadata"] = self.process_metadata
|
process_instance_attributes["process_metadata"] = self.process_metadata
|
||||||
process_instance_attributes[
|
process_instance_attributes["process_model_with_diagram_identifier"] = (
|
||||||
"process_model_with_diagram_identifier"
|
self.process_model_with_diagram_identifier
|
||||||
] = self.process_model_with_diagram_identifier
|
)
|
||||||
return process_instance_attributes
|
return process_instance_attributes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -423,9 +423,9 @@ class ProcessInstanceProcessor:
|
|||||||
tld.process_instance_id = process_instance_model.id
|
tld.process_instance_id = process_instance_model.id
|
||||||
|
|
||||||
# we want this to be the fully qualified path to the process model including all group subcomponents
|
# we want this to be the fully qualified path to the process model including all group subcomponents
|
||||||
current_app.config[
|
current_app.config["THREAD_LOCAL_DATA"].process_model_identifier = (
|
||||||
"THREAD_LOCAL_DATA"
|
f"{process_instance_model.process_model_identifier}"
|
||||||
].process_model_identifier = f"{process_instance_model.process_model_identifier}"
|
)
|
||||||
|
|
||||||
self.process_instance_model = process_instance_model
|
self.process_instance_model = process_instance_model
|
||||||
self.process_model_service = ProcessModelService()
|
self.process_model_service = ProcessModelService()
|
||||||
@ -585,9 +585,9 @@ class ProcessInstanceProcessor:
|
|||||||
bpmn_subprocess_definition.bpmn_identifier
|
bpmn_subprocess_definition.bpmn_identifier
|
||||||
] = bpmn_process_definition_dict
|
] = bpmn_process_definition_dict
|
||||||
spiff_bpmn_process_dict["subprocess_specs"][bpmn_subprocess_definition.bpmn_identifier]["task_specs"] = {}
|
spiff_bpmn_process_dict["subprocess_specs"][bpmn_subprocess_definition.bpmn_identifier]["task_specs"] = {}
|
||||||
bpmn_subprocess_definition_bpmn_identifiers[
|
bpmn_subprocess_definition_bpmn_identifiers[bpmn_subprocess_definition.id] = (
|
||||||
bpmn_subprocess_definition.id
|
bpmn_subprocess_definition.bpmn_identifier
|
||||||
] = bpmn_subprocess_definition.bpmn_identifier
|
)
|
||||||
|
|
||||||
task_definitions = TaskDefinitionModel.query.filter(
|
task_definitions = TaskDefinitionModel.query.filter(
|
||||||
TaskDefinitionModel.bpmn_process_definition_id.in_( # type: ignore
|
TaskDefinitionModel.bpmn_process_definition_id.in_( # type: ignore
|
||||||
|
@ -34,7 +34,11 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelSer
|
|||||||
|
|
||||||
|
|
||||||
class ProcessInstanceReportNotFoundError(Exception):
|
class ProcessInstanceReportNotFoundError(Exception):
|
||||||
"""ProcessInstanceReportNotFoundError."""
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ProcessInstanceReportMetadataInvalidError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ProcessInstanceReportService:
|
class ProcessInstanceReportService:
|
||||||
@ -441,6 +445,15 @@ class ProcessInstanceReportService:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if with_tasks_completed_by_me is True and with_tasks_i_can_complete is True:
|
||||||
|
raise ProcessInstanceReportMetadataInvalidError(
|
||||||
|
"Cannot set both 'with_tasks_completed_by_me' and 'with_tasks_i_can_complete' to true. You must choose"
|
||||||
|
" one."
|
||||||
|
)
|
||||||
|
|
||||||
|
# ensure we only join with HumanTaskModel once
|
||||||
|
human_task_already_joined = False
|
||||||
|
|
||||||
if with_tasks_completed_by_me is True:
|
if with_tasks_completed_by_me is True:
|
||||||
process_instance_query = process_instance_query.filter(
|
process_instance_query = process_instance_query.filter(
|
||||||
ProcessInstanceModel.process_initiator_id != user.id
|
ProcessInstanceModel.process_initiator_id != user.id
|
||||||
@ -452,6 +465,7 @@ class ProcessInstanceReportService:
|
|||||||
HumanTaskModel.completed_by_user_id == user.id,
|
HumanTaskModel.completed_by_user_id == user.id,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
human_task_already_joined = True
|
||||||
|
|
||||||
# this excludes some tasks you can complete, because that's the way the requirements were described.
|
# this excludes some tasks you can complete, because that's the way the requirements were described.
|
||||||
# if it's assigned to one of your groups, it does not get returned by this query.
|
# if it's assigned to one of your groups, it does not get returned by this query.
|
||||||
@ -470,13 +484,15 @@ class ProcessInstanceReportService:
|
|||||||
HumanTaskUserModel,
|
HumanTaskUserModel,
|
||||||
and_(HumanTaskUserModel.human_task_id == HumanTaskModel.id, HumanTaskUserModel.user_id == user.id),
|
and_(HumanTaskUserModel.human_task_id == HumanTaskModel.id, HumanTaskUserModel.user_id == user.id),
|
||||||
)
|
)
|
||||||
|
human_task_already_joined = True
|
||||||
|
|
||||||
if user_group_identifier is not None:
|
if user_group_identifier is not None:
|
||||||
group_model_join_conditions = [GroupModel.id == HumanTaskModel.lane_assignment_id]
|
group_model_join_conditions = [GroupModel.id == HumanTaskModel.lane_assignment_id]
|
||||||
if user_group_identifier:
|
if user_group_identifier:
|
||||||
group_model_join_conditions.append(GroupModel.identifier == user_group_identifier)
|
group_model_join_conditions.append(GroupModel.identifier == user_group_identifier)
|
||||||
|
|
||||||
process_instance_query = process_instance_query.join(HumanTaskModel)
|
if human_task_already_joined is False:
|
||||||
|
process_instance_query = process_instance_query.join(HumanTaskModel)
|
||||||
if process_status is not None:
|
if process_status is not None:
|
||||||
non_active_statuses = [
|
non_active_statuses = [
|
||||||
s for s in process_status.split(",") if s not in ProcessInstanceModel.active_statuses()
|
s for s in process_status.split(",") if s not in ProcessInstanceModel.active_statuses()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"""Test_process_instance_report_service."""
|
"""Test_process_instance_report_service."""
|
||||||
|
import pytest
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask.testing import FlaskClient
|
from flask.testing import FlaskClient
|
||||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||||
@ -7,9 +8,9 @@ from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
|||||||
from spiffworkflow_backend.models.db import db
|
from spiffworkflow_backend.models.db import db
|
||||||
from spiffworkflow_backend.models.group import GroupModel
|
from spiffworkflow_backend.models.group import GroupModel
|
||||||
from spiffworkflow_backend.models.human_task import HumanTaskModel
|
from spiffworkflow_backend.models.human_task import HumanTaskModel
|
||||||
from spiffworkflow_backend.services.process_instance_report_service import (
|
from spiffworkflow_backend.models.process_instance_report import ReportMetadata
|
||||||
ProcessInstanceReportService,
|
from spiffworkflow_backend.services.process_instance_report_service import ProcessInstanceReportMetadataInvalidError
|
||||||
)
|
from spiffworkflow_backend.services.process_instance_report_service import ProcessInstanceReportService
|
||||||
from spiffworkflow_backend.services.user_service import UserService
|
from spiffworkflow_backend.services.user_service import UserService
|
||||||
|
|
||||||
|
|
||||||
@ -52,6 +53,62 @@ class TestProcessInstanceReportService(BaseTest):
|
|||||||
assert response_json["results"][0]["status"] == "complete"
|
assert response_json["results"][0]["status"] == "complete"
|
||||||
assert response_json["results"][1]["status"] == "complete"
|
assert response_json["results"][1]["status"] == "complete"
|
||||||
|
|
||||||
|
def test_raises_if_filtering_with_both_task_i_can_complete_and_tasks_completed_by_me(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
) -> None:
|
||||||
|
user_one = self.find_or_create_user(username="user_one")
|
||||||
|
report_metadata: ReportMetadata = {
|
||||||
|
"columns": [],
|
||||||
|
"filter_by": [
|
||||||
|
{"field_name": "with_tasks_i_can_complete", "field_value": True, "operator": "equals"},
|
||||||
|
{"field_name": "with_tasks_completed_by_me", "field_value": True, "operator": "equals"},
|
||||||
|
],
|
||||||
|
"order_by": [],
|
||||||
|
}
|
||||||
|
with pytest.raises(ProcessInstanceReportMetadataInvalidError):
|
||||||
|
ProcessInstanceReportService.run_process_instance_report(
|
||||||
|
report_metadata=report_metadata,
|
||||||
|
user=user_one,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_with_group_identifier_does_not_conflict_with_system_filters(
|
||||||
|
self,
|
||||||
|
app: Flask,
|
||||||
|
client: FlaskClient,
|
||||||
|
with_db_and_bpmn_file_cleanup: None,
|
||||||
|
) -> None:
|
||||||
|
user_one = self.find_or_create_user(username="user_one")
|
||||||
|
report_metadata: ReportMetadata = {
|
||||||
|
"columns": [],
|
||||||
|
"filter_by": [
|
||||||
|
{"field_name": "with_tasks_i_can_complete", "field_value": True, "operator": "equals"},
|
||||||
|
{"field_name": "user_group_identifier", "field_value": "group_one", "operator": "equals"},
|
||||||
|
],
|
||||||
|
"order_by": [],
|
||||||
|
}
|
||||||
|
result = ProcessInstanceReportService.run_process_instance_report(
|
||||||
|
report_metadata=report_metadata,
|
||||||
|
user=user_one,
|
||||||
|
)
|
||||||
|
assert result is not None
|
||||||
|
|
||||||
|
report_metadata = {
|
||||||
|
"columns": [],
|
||||||
|
"filter_by": [
|
||||||
|
{"field_name": "with_tasks_completed_by_me", "field_value": True, "operator": "equals"},
|
||||||
|
{"field_name": "user_group_identifier", "field_value": "group_one", "operator": "equals"},
|
||||||
|
],
|
||||||
|
"order_by": [],
|
||||||
|
}
|
||||||
|
result = ProcessInstanceReportService.run_process_instance_report(
|
||||||
|
report_metadata=report_metadata,
|
||||||
|
user=user_one,
|
||||||
|
)
|
||||||
|
assert result is not None
|
||||||
|
|
||||||
def test_can_filter_by_completed_instances_with_tasks_completed_by_me(
|
def test_can_filter_by_completed_instances_with_tasks_completed_by_me(
|
||||||
self,
|
self,
|
||||||
app: Flask,
|
app: Flask,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user