remove a lot of unused code and fixed linting issues w/ burnettk

This commit is contained in:
jasquat 2023-04-27 17:33:25 -04:00
parent b86ddf8a96
commit a4fd81cb9a
13 changed files with 301 additions and 1735 deletions

View File

@ -1,108 +0,0 @@
"""Import tickets, for use in script task."""
def main():
"""Use main to avoid global namespace."""
import csv
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor,
)
from spiffworkflow_backend.services.process_instance_service import (
ProcessInstanceService,
)
from spiffworkflow_backend.models.process_instance_report import (
ProcessInstanceReportModel,
)
process_model_identifier_ticket = "ticket"
db.session.query(ProcessInstanceModel).filter(
ProcessInstanceModel.process_model_identifier == process_model_identifier_ticket
).delete()
db.session.commit()
"""Print process instance count."""
process_instances = ProcessInstanceModel.query.filter_by(
process_model_identifier=process_model_identifier_ticket
).all()
process_instance_count = len(process_instances)
print(f"process_instance_count: {process_instance_count}")
columns_to_data_key_mappings = {
"Month": "month",
"MS": "milestone",
"Done?": "done",
"#": "notion_id",
"ID": "req_id",
"Dev Days": "dev_days",
"Feature": "feature",
"Feature description": "feature_description",
"Priority": "priority",
}
columns_to_header_index_mappings = {}
user = UserModel.query.first()
with open("tests/files/tickets.csv") as infile:
reader = csv.reader(infile, delimiter=",")
# first row is garbage
next(reader)
header = next(reader)
for column_name in columns_to_data_key_mappings:
columns_to_header_index_mappings[column_name] = header.index(column_name)
id_index = header.index("ID")
priority_index = header.index("Priority")
month_index = header.index("Month")
print(f"header: {header}")
for row in reader:
ticket_identifier = row[id_index]
priority = row[priority_index]
month = row[month_index]
print(f"ticket_identifier: {ticket_identifier}")
print(f"priority: {priority}")
# if there is no month, who cares about it.
if month:
process_instance = ProcessInstanceService.create_process_instance_from_process_model_identifier(
process_model_identifier=process_model_identifier_ticket,
user=user,
process_group_identifier="sartography-admin",
)
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps()
# processor.save()
for (
column_name,
desired_data_key,
) in columns_to_data_key_mappings.items():
appropriate_index = columns_to_header_index_mappings[column_name]
print(f"appropriate_index: {appropriate_index}")
processor.bpmn_process_instance.data[desired_data_key] = row[appropriate_index]
# you at least need a month, or else this row in the csv is considered garbage
month_value = processor.bpmn_process_instance.data["month"]
if month_value == "" or month_value is None:
db.session.delete(process_instance)
db.session.commit()
continue
processor.save()
process_instance_data = processor.get_data()
print(f"process_instance_data: {process_instance_data}")
ProcessInstanceReportModel.add_fixtures()
print("added report fixtures")
main()
# to avoid serialization issues
del main

View File

@ -1,8 +1,10 @@
from __future__ import annotations
import json
from hashlib import sha256
from flask import current_app
from typing import TypedDict
from flask import current_app
from sqlalchemy.dialects.mysql import insert as mysql_insert
from sqlalchemy.dialects.postgresql import insert as postgres_insert
@ -76,6 +78,6 @@ class JsonDataModel(SpiffworkflowBaseDBModel):
@classmethod
def create_and_insert_json_data_from_dict(cls, data: dict) -> str:
json_data_hash = sha256(json.dumps(data, sort_keys=True).encode("utf8")).hexdigest()
cls.insert_or_update_json_data_dict({'hash': json_data_hash, 'data': data})
cls.insert_or_update_json_data_dict({"hash": json_data_hash, "data": data})
db.session.commit()
return json_data_hash

View File

@ -1,21 +1,20 @@
"""Process_instance."""
from __future__ import annotations
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
import typing
from dataclasses import dataclass
from typing import Any
from typing import cast
from typing import NotRequired
from typing import Optional
from typing import TypedDict
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError,
)
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.db import SpiffworkflowBaseDBModel
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import (
@ -25,13 +24,14 @@ from spiffworkflow_backend.services.process_instance_processor import (
class FilterValue(TypedDict):
field_name: str
field_value: str
operator: str
field_value: str | int | bool
operator: NotRequired[str]
class ReportMetadataColumn(TypedDict):
Header: str
accessor: str
filterable: NotRequired[bool]
class ReportMetadata(TypedDict):
@ -83,7 +83,7 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
id: int = db.Column(db.Integer, primary_key=True)
identifier: str = db.Column(db.String(50), nullable=False, index=True)
report_metadata: dict = db.Column(db.JSON)
report_metadata: ReportMetadata = db.Column(db.JSON)
created_by_id = db.Column(ForeignKey(UserModel.id), nullable=False, index=True) # type: ignore
created_by = relationship("UserModel")
created_at_in_seconds = db.Column(db.Integer)
@ -99,49 +99,6 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
"""Default_order_by."""
return ["-start_in_seconds", "-id"]
@classmethod
def add_fixtures(cls) -> None:
"""Add_fixtures."""
try:
# process_model = ProcessModelService.get_process_model(
# process_model_id="sartography-admin/ticket"
# )
user = UserModel.query.first()
columns = [
{"Header": "id", "accessor": "id"},
{"Header": "month", "accessor": "month"},
{"Header": "milestone", "accessor": "milestone"},
{"Header": "req_id", "accessor": "req_id"},
{"Header": "feature", "accessor": "feature"},
{"Header": "dev_days", "accessor": "dev_days"},
{"Header": "priority", "accessor": "priority"},
]
json = {"order": "month asc", "columns": columns}
cls.create_report(
identifier="standard",
user=user,
report_metadata=json,
)
cls.create_report(
identifier="for-month",
user=user,
report_metadata=cls.ticket_for_month_report(),
)
cls.create_report(
identifier="for-month-3",
user=user,
report_metadata=cls.ticket_for_month_3_report(),
)
cls.create_report(
identifier="hot-report",
user=user,
report_metadata=cls.process_model_with_form_report_fixture(),
)
except ProcessEntityNotFoundError:
print("Did not find process models so not adding report fixtures for them")
@classmethod
def create_report(
cls,
@ -160,7 +117,8 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
f"Process instance report with identifier already exists: {identifier}"
)
json_data_hash = JsonDataModel.create_and_insert_json_data_from_dict(report_metadata)
report_metadata_dict = typing.cast(typing.Dict[str, Any], report_metadata)
json_data_hash = JsonDataModel.create_and_insert_json_data_from_dict(report_metadata_dict)
process_instance_report = cls(
identifier=identifier,
@ -173,69 +131,11 @@ class ProcessInstanceReportModel(SpiffworkflowBaseDBModel):
return process_instance_report # type: ignore
@classmethod
def ticket_for_month_report(cls) -> dict:
"""Ticket_for_month_report."""
return {
"columns": [
{"Header": "id", "accessor": "id"},
{"Header": "month", "accessor": "month"},
{"Header": "milestone", "accessor": "milestone"},
{"Header": "req_id", "accessor": "req_id"},
{"Header": "feature", "accessor": "feature"},
{"Header": "priority", "accessor": "priority"},
],
"order": "month asc",
"filter_by": [
{
"field_name": "month",
"operator": "equals",
"field_value": "{{month}}",
}
],
}
@classmethod
def ticket_for_month_3_report(cls) -> dict:
"""Ticket_for_month_report."""
return {
"columns": [
{"Header": "id", "accessor": "id"},
{"Header": "month", "accessor": "month"},
{"Header": "milestone", "accessor": "milestone"},
{"Header": "req_id", "accessor": "req_id"},
{"Header": "feature", "accessor": "feature"},
{"Header": "dev_days", "accessor": "dev_days"},
{"Header": "priority", "accessor": "priority"},
],
"order": "month asc",
"filter_by": [{"field_name": "month", "operator": "equals", "field_value": "3"}],
}
@classmethod
def process_model_with_form_report_fixture(cls) -> dict:
"""Process_model_with_form_report_fixture."""
return {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "system_generated_number",
"accessor": "system_generated_number",
},
{
"Header": "user_generated_number",
"accessor": "user_generated_number",
},
{"Header": "product", "accessor": "product"},
],
"order": "-id",
}
@classmethod
def create_with_attributes(
cls,
identifier: str,
report_metadata: dict,
report_metadata: ReportMetadata,
user: UserModel,
) -> ProcessInstanceReportModel:
"""Create_with_attributes."""

View File

@ -1,7 +1,4 @@
"""APIs for dealing with process groups, process models, and process instances."""
import base64
from hashlib import sha256
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
import json
from typing import Any
from typing import Dict
@ -12,7 +9,6 @@ from flask import current_app
from flask import g
from flask import jsonify
from flask import make_response
from flask import request
from flask.wrappers import Response
from sqlalchemy import and_
from sqlalchemy import or_
@ -26,6 +22,7 @@ from spiffworkflow_backend.models.bpmn_process_definition import (
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema
from spiffworkflow_backend.models.process_instance import (
ProcessInstanceCannotBeDeletedError,
@ -70,9 +67,6 @@ from spiffworkflow_backend.services.process_instance_queue_service import (
from spiffworkflow_backend.services.process_instance_queue_service import (
ProcessInstanceQueueService,
)
# from spiffworkflow_backend.services.process_instance_report_service import (
# ProcessInstanceReportFilter,
# )
from spiffworkflow_backend.services.process_instance_report_service import (
ProcessInstanceReportService,
)
@ -83,6 +77,10 @@ from spiffworkflow_backend.services.process_model_service import ProcessModelSer
from spiffworkflow_backend.services.spec_file_service import SpecFileService
from spiffworkflow_backend.services.task_service import TaskService
# from spiffworkflow_backend.services.process_instance_report_service import (
# ProcessInstanceReportFilter,
# )
def process_instance_create(
modified_process_model_identifier: str,
@ -232,38 +230,13 @@ def process_instance_list_for_me(
process_model_identifier: Optional[str] = None,
page: int = 1,
per_page: int = 100,
# start_from: Optional[int] = None,
# start_to: Optional[int] = None,
# end_from: Optional[int] = None,
# end_to: Optional[int] = None,
# process_status: Optional[str] = None,
# user_filter: Optional[bool] = False,
# report_identifier: Optional[str] = None,
# report_id: Optional[int] = None,
# user_group_identifier: Optional[str] = None,
# process_initiator_username: Optional[str] = None,
# report_columns: Optional[str] = None,
# report_filter_by: Optional[str] = None,
) -> flask.wrappers.Response:
"""Process_instance_list_for_me."""
return process_instance_list(
process_model_identifier=process_model_identifier,
page=page,
per_page=per_page,
# start_from=start_from,
# start_to=start_to,
# end_from=end_from,
# end_to=end_to,
# process_status=process_status,
# user_filter=user_filter,
# report_identifier=report_identifier,
# report_id=report_id,
# user_group_identifier=user_group_identifier,
# with_relation_to_me=True,
# report_columns=report_columns,
# report_filter_by=report_filter_by,
# process_initiator_username=process_initiator_username,
body=body
body=body,
)
@ -272,71 +245,16 @@ def process_instance_list(
process_model_identifier: Optional[str] = None,
page: int = 1,
per_page: int = 100,
# start_from: Optional[int] = None,
# start_to: Optional[int] = None,
# end_from: Optional[int] = None,
# end_to: Optional[int] = None,
# process_status: Optional[str] = None,
# with_relation_to_me: Optional[bool] = None,
# user_filter: Optional[bool] = False,
# report_identifier: Optional[str] = None,
# report_id: Optional[int] = None,
# user_group_identifier: Optional[str] = None,
# process_initiator_username: Optional[str] = None,
# report_columns: Optional[str] = None,
# report_filter_by: Optional[str] = None,
) -> flask.wrappers.Response:
# process_instance_report = ProcessInstanceReportService.report_with_identifier(g.user, body['report_id'], body['report_identifier'])
process_instance_report = ProcessInstanceReportService.report_with_identifier(g.user)
# report_column_list = None
# if report_columns:
# report_column_list = json.loads(base64.b64decode(report_columns))
# report_filter_by_list = None
# if report_filter_by:
# report_filter_by_list = json.loads(base64.b64decode(report_filter_by))
# if user_filter:
# report_filter = ProcessInstanceReportFilter(
# process_model_identifier=process_model_identifier,
# # user_group_identifier=user_group_identifier,
# # start_from=start_from,
# # start_to=start_to,
# # end_from=end_from,
# # end_to=end_to,
# # with_relation_to_me=with_relation_to_me,
# # process_status=process_status.split(",") if process_status else None,
# # process_initiator_username=process_initiator_username,
# # report_column_list=report_column_list,
# # report_filter_by_list=report_filter_by_list,
# )
# else:
# report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
# process_instance_report=process_instance_report,
# process_model_identifier=process_model_identifier,
# # user_group_identifier=user_group_identifier,
# # start_from=start_from,
# # start_to=start_to,
# # end_from=end_from,
# # end_to=end_to,
# # process_status=process_status,
# # with_relation_to_me=with_relation_to_me,
# # process_initiator_username=process_initiator_username,
# # report_column_list=report_column_list,
# # report_filter_by_list=report_filter_by_list,
# )
response_json = ProcessInstanceReportService.run_process_instance_report(
# report_filter=report_filter,
report_metadata=body['report_metadata'],
process_instance_report=process_instance_report,
report_metadata=body["report_metadata"],
page=page,
per_page=per_page,
user=g.user,
)
json_data_hash = JsonDataModel.create_and_insert_json_data_from_dict(body['report_metadata'])
response_json['report_hash'] = json_data_hash
json_data_hash = JsonDataModel.create_and_insert_json_data_from_dict(body["report_metadata"])
response_json["report_hash"] = json_data_hash
db.session.commit()
return make_response(jsonify(response_json), 200)
@ -347,11 +265,13 @@ def process_instance_report_show(
report_id: Optional[int] = None,
report_identifier: Optional[str] = None,
) -> flask.wrappers.Response:
if report_hash is None and report_id is None and report_identifier is None:
raise ApiError(
error_code="report_key_missing",
message="A report key is needed to lookup a report. Either choose a report_hash, report_id, or report_identifier.",
message=(
"A report key is needed to lookup a report. Either choose a report_hash, report_id, or"
" report_identifier."
),
)
response_result = {}
if report_hash is not None:
@ -454,7 +374,6 @@ def process_instance_report_list(page: int = 1, per_page: int = 100) -> flask.wr
def process_instance_report_create(body: Dict[str, Any]) -> flask.wrappers.Response:
"""Process_instance_report_create."""
process_instance_report = ProcessInstanceReportModel.create_report(
identifier=body["identifier"],
user=g.user,
@ -541,6 +460,7 @@ def process_instance_report_delete(
# return Response(json.dumps(result_dict), status=200, mimetype="application/json")
#
def process_instance_task_list_without_task_data_for_me(
modified_process_model_identifier: str,
process_instance_id: int,

View File

@ -1,6 +1,5 @@
"""APIs for dealing with process groups, process models, and process instances."""
import json
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
import os
import uuid
from sys import exc_info
@ -37,6 +36,7 @@ from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.human_task_user import HumanTaskUserModel
from spiffworkflow_backend.models.json_data import JsonDataModel # noqa: F401
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus

View File

@ -1,7 +1,7 @@
"""Process_instance_report_service."""
import re
from dataclasses import dataclass
from typing import Any, Generator, Iterable
from typing import Any
from typing import Generator
from typing import Optional
from typing import Type
@ -23,11 +23,10 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel,
)
from spiffworkflow_backend.models.process_instance_report import (
FilterValue,
ProcessInstanceReportModel,
ReportMetadata,
)
from spiffworkflow_backend.models.process_instance_report import FilterValue
from spiffworkflow_backend.models.process_instance_report import ProcessInstanceReportModel
from spiffworkflow_backend.models.process_instance_report import ReportMetadata
from spiffworkflow_backend.models.process_instance_report import ReportMetadataColumn
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.models.user_group_assignment import UserGroupAssignmentModel
from spiffworkflow_backend.services.process_model_service import ProcessModelService
@ -37,196 +36,144 @@ class ProcessInstanceReportNotFoundError(Exception):
"""ProcessInstanceReportNotFoundError."""
# @dataclass
# class ProcessInstanceReportFilter:
# """ProcessInstanceReportFilter."""
#
# process_model_identifier: Optional[str] = None
# user_group_identifier: Optional[str] = None
# start_from: Optional[int] = None
# start_to: Optional[int] = None
# end_from: Optional[int] = None
# end_to: Optional[int] = None
# process_status: Optional[list[str]] = None
# initiated_by_me: Optional[bool] = None
# has_terminal_status: Optional[bool] = None
# has_active_status: Optional[bool] = None
# with_tasks_completed_by_me: Optional[bool] = None
# with_tasks_i_can_complete: Optional[bool] = None
# with_tasks_assigned_to_my_group: Optional[bool] = None
# with_relation_to_me: Optional[bool] = None
# process_initiator_username: Optional[str] = None
# report_column_list: Optional[list] = None
# report_filter_by_list: Optional[list] = None
# oldest_open_human_task_fields: Optional[list] = None
#
# def to_dict(self) -> dict[str, str]:
# """To_dict."""
# d = {}
#
# if self.process_model_identifier is not None:
# d["process_model_identifier"] = self.process_model_identifier
# if self.user_group_identifier is not None:
# d["user_group_identifier"] = self.user_group_identifier
# if self.start_from is not None:
# d["start_from"] = str(self.start_from)
# if self.start_to is not None:
# d["start_to"] = str(self.start_to)
# if self.end_from is not None:
# d["end_from"] = str(self.end_from)
# if self.end_to is not None:
# d["end_to"] = str(self.end_to)
# if self.process_status is not None:
# d["process_status"] = ",".join(self.process_status)
# if self.initiated_by_me is not None:
# d["initiated_by_me"] = str(self.initiated_by_me).lower()
# if self.has_terminal_status is not None:
# d["has_terminal_status"] = str(self.has_terminal_status).lower()
# if self.has_active_status is not None:
# d["has_active_status"] = str(self.has_active_status).lower()
# if self.with_tasks_completed_by_me is not None:
# d["with_tasks_completed_by_me"] = str(self.with_tasks_completed_by_me).lower()
# if self.with_tasks_i_can_complete is not None:
# d["with_tasks_i_can_complete"] = str(self.with_tasks_i_can_complete).lower()
# if self.with_tasks_assigned_to_my_group is not None:
# d["with_tasks_assigned_to_my_group"] = str(self.with_tasks_assigned_to_my_group).lower()
# if self.with_relation_to_me is not None:
# d["with_relation_to_me"] = str(self.with_relation_to_me).lower()
# if self.process_initiator_username is not None:
# d["process_initiator_username"] = str(self.process_initiator_username)
# if self.report_column_list is not None:
# d["report_column_list"] = str(self.report_column_list)
# if self.report_filter_by_list is not None:
# d["report_filter_by_list"] = str(self.report_filter_by_list)
# if self.oldest_open_human_task_fields is not None:
# d["oldest_open_human_task_fields"] = str(self.oldest_open_human_task_fields)
#
# return d
class ProcessInstanceReportService:
"""ProcessInstanceReportService."""
@classmethod
def system_metadata_map(cls, metadata_key: str) -> Optional[dict[str, Any]]:
def system_metadata_map(cls, metadata_key: str) -> Optional[ReportMetadata]:
"""System_metadata_map."""
# TODO replace with system reports that are loaded on launch (or similar)
temp_system_metadata_map = {
"default": {
"columns": cls.builtin_column_options(),
"filter_by": [],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_completed_instances_initiated_by_me": {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
{"Header": "status", "accessor": "status"},
],
"filter_by": [
{"field_name": "initiated_by_me", "field_value": "true"},
{"field_name": "has_terminal_status", "field_value": "true"},
],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_completed_instances_with_tasks_completed_by_me": {
"columns": cls.builtin_column_options(),
"filter_by": [
{"field_name": "with_tasks_completed_by_me", "field_value": "true"},
{"field_name": "has_terminal_status", "field_value": "true"},
],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_completed_instances_with_tasks_completed_by_my_groups": {
"columns": cls.builtin_column_options(),
"filter_by": [
{
"field_name": "with_tasks_assigned_to_my_group",
"field_value": "true",
},
{"field_name": "has_terminal_status", "field_value": "true"},
],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_in_progress_instances_initiated_by_me": {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Waiting For", "accessor": "waiting_for"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
{"Header": "status", "accessor": "status"},
],
"filter_by": [
{"field_name": "initiated_by_me", "field_value": "true"},
{"field_name": "has_terminal_status", "field_value": "false"},
{
"field_name": "oldest_open_human_task_fields",
"field_value": (
"task_id,task_title,task_name,potential_owner_usernames,assigned_user_group_identifier"
),
},
],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_in_progress_instances_with_tasks_for_me": {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [
{"field_name": "with_tasks_i_can_complete", "field_value": "true"},
{"field_name": "has_active_status", "field_value": "true"},
{
"field_name": "oldest_open_human_task_fields",
"field_value": "task_id,task_title,task_name",
},
],
"order_by": ["-start_in_seconds", "-id"],
},
"system_report_in_progress_instances_with_tasks_for_my_group": {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [
{
"field_name": "with_tasks_assigned_to_my_group",
"field_value": "true",
},
{"field_name": "has_active_status", "field_value": "true"},
{
"field_name": "oldest_open_human_task_fields",
"field_value": "task_id,task_title,task_name",
},
],
"order_by": ["-start_in_seconds", "-id"],
},
default: ReportMetadata = {
"columns": cls.builtin_column_options(),
"filter_by": [],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_completed_instances_initiated_by_me: ReportMetadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "start_in_seconds", "accessor": "start_in_seconds"},
{"Header": "end_in_seconds", "accessor": "end_in_seconds"},
{"Header": "status", "accessor": "status"},
],
"filter_by": [
{"field_name": "initiated_by_me", "field_value": True},
{"field_name": "has_terminal_status", "field_value": True},
],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_completed_instances_with_tasks_completed_by_me: ReportMetadata = {
"columns": cls.builtin_column_options(),
"filter_by": [
{"field_name": "with_tasks_completed_by_me", "field_value": True},
{"field_name": "has_terminal_status", "field_value": True},
],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_completed_instances_with_tasks_completed_by_my_groups: ReportMetadata = {
"columns": cls.builtin_column_options(),
"filter_by": [
{
"field_name": "with_tasks_assigned_to_my_group",
"field_value": True,
},
{"field_name": "has_terminal_status", "field_value": True},
],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_in_progress_instances_initiated_by_me: ReportMetadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Waiting For", "accessor": "waiting_for"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
{"Header": "status", "accessor": "status"},
],
"filter_by": [
{"field_name": "initiated_by_me", "field_value": True},
{"field_name": "has_terminal_status", "field_value": False},
{
"field_name": "oldest_open_human_task_fields",
"field_value": (
"task_id,task_title,task_name,potential_owner_usernames,assigned_user_group_identifier"
),
},
],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_in_progress_instances_with_tasks_for_me: ReportMetadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [
{"field_name": "with_tasks_i_can_complete", "field_value": True},
{"field_name": "has_active_status", "field_value": True},
{
"field_name": "oldest_open_human_task_fields",
"field_value": "task_id,task_title,task_name",
},
],
"order_by": ["-start_in_seconds", "-id"],
}
system_report_in_progress_instances_with_tasks_for_my_group: ReportMetadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{
"Header": "process_model_display_name",
"accessor": "process_model_display_name",
},
{"Header": "Task", "accessor": "task_title"},
{"Header": "Started By", "accessor": "process_initiator_username"},
{"Header": "Started", "accessor": "start_in_seconds"},
{"Header": "Last Updated", "accessor": "updated_at_in_seconds"},
],
"filter_by": [
{
"field_name": "with_tasks_assigned_to_my_group",
"field_value": True,
},
{"field_name": "has_active_status", "field_value": True},
{
"field_name": "oldest_open_human_task_fields",
"field_value": "task_id,task_title,task_name",
},
],
"order_by": ["-start_in_seconds", "-id"],
}
temp_system_metadata_map = {
"default": default,
"system_report_completed_instances_initiated_by_me": system_report_completed_instances_initiated_by_me,
"system_report_completed_instances_with_tasks_completed_by_me": (
system_report_completed_instances_with_tasks_completed_by_me
),
"system_report_completed_instances_with_tasks_completed_by_my_groups": (
system_report_completed_instances_with_tasks_completed_by_my_groups
),
"system_report_in_progress_instances_initiated_by_me": system_report_in_progress_instances_initiated_by_me,
"system_report_in_progress_instances_with_tasks_for_me": (
system_report_in_progress_instances_with_tasks_for_me
),
"system_report_in_progress_instances_with_tasks_for_my_group": (
system_report_in_progress_instances_with_tasks_for_my_group
),
}
if metadata_key not in temp_system_metadata_map:
return None
return temp_system_metadata_map[metadata_key]
@ -268,160 +215,20 @@ class ProcessInstanceReportService:
return process_instance_report # type: ignore
# @classmethod
# def filter_by_to_dict(cls, process_instance_report: ProcessInstanceReportModel) -> dict[str, str]:
# """Filter_by_to_dict."""
# metadata = process_instance_report.report_metadata
# filter_by = metadata.get("filter_by", [])
# filters = {d["field_name"]: d["field_value"] for d in filter_by if "field_name" in d and "field_value" in d}
# return filters
#
# @classmethod
# def filter_from_metadata(cls, process_instance_report: ProcessInstanceReportModel) -> ProcessInstanceReportFilter:
# """Filter_from_metadata."""
# filters = cls.filter_by_to_dict(process_instance_report)
#
# def bool_value(key: str) -> Optional[bool]:
# """Bool_value."""
# if key not in filters:
# return None
# # bool returns True if not an empty string so check explicitly for false
# if filters[key] in ["false", "False"]:
# return False
# return bool(filters[key])
#
# def int_value(key: str) -> Optional[int]:
# """Int_value."""
# return int(filters[key]) if key in filters else None
#
# def list_value(key: str) -> Optional[list[str]]:
# return filters[key].split(",") if key in filters else None
#
# process_model_identifier = filters.get("process_model_identifier")
# user_group_identifier = filters.get("user_group_identifier")
# start_from = int_value("start_from")
# start_to = int_value("start_to")
# end_from = int_value("end_from")
# end_to = int_value("end_to")
# process_status = list_value("process_status")
# initiated_by_me = bool_value("initiated_by_me")
# has_terminal_status = bool_value("has_terminal_status")
# has_active_status = bool_value("has_active_status")
# with_tasks_completed_by_me = bool_value("with_tasks_completed_by_me")
# with_tasks_i_can_complete = bool_value("with_tasks_i_can_complete")
# with_tasks_assigned_to_my_group = bool_value("with_tasks_assigned_to_my_group")
# with_relation_to_me = bool_value("with_relation_to_me")
# process_initiator_username = filters.get("process_initiator_username")
# report_column_list = list_value("report_column_list")
# report_filter_by_list = list_value("report_filter_by_list")
# oldest_open_human_task_fields = list_value("oldest_open_human_task_fields")
#
# report_filter = ProcessInstanceReportFilter(
# process_model_identifier=process_model_identifier,
# user_group_identifier=user_group_identifier,
# start_from=start_from,
# start_to=start_to,
# end_from=end_from,
# end_to=end_to,
# process_status=process_status,
# initiated_by_me=initiated_by_me,
# has_terminal_status=has_terminal_status,
# has_active_status=has_active_status,
# with_tasks_completed_by_me=with_tasks_completed_by_me,
# with_tasks_i_can_complete=with_tasks_i_can_complete,
# with_tasks_assigned_to_my_group=with_tasks_assigned_to_my_group,
# with_relation_to_me=with_relation_to_me,
# process_initiator_username=process_initiator_username,
# report_column_list=report_column_list,
# report_filter_by_list=report_filter_by_list,
# oldest_open_human_task_fields=oldest_open_human_task_fields,
# )
#
# return report_filter
#
# @classmethod
# def filter_from_metadata_with_overrides(
# cls,
# process_instance_report: ProcessInstanceReportModel,
# process_model_identifier: Optional[str] = None,
# user_group_identifier: Optional[str] = None,
# start_from: Optional[int] = None,
# start_to: Optional[int] = None,
# end_from: Optional[int] = None,
# end_to: Optional[int] = None,
# process_status: Optional[str] = None,
# initiated_by_me: Optional[bool] = None,
# has_terminal_status: Optional[bool] = None,
# has_active_status: Optional[bool] = None,
# with_tasks_completed_by_me: Optional[bool] = None,
# with_tasks_i_can_complete: Optional[bool] = None,
# with_tasks_assigned_to_my_group: Optional[bool] = None,
# with_relation_to_me: Optional[bool] = None,
# process_initiator_username: Optional[str] = None,
# report_column_list: Optional[list] = None,
# report_filter_by_list: Optional[list] = None,
# oldest_open_human_task_fields: Optional[list] = None,
# ) -> ProcessInstanceReportFilter:
# """Filter_from_metadata_with_overrides."""
# report_filter = cls.filter_from_metadata(process_instance_report)
#
# if process_model_identifier is not None:
# report_filter.process_model_identifier = process_model_identifier
# if user_group_identifier is not None:
# report_filter.user_group_identifier = user_group_identifier
# if start_from is not None:
# report_filter.start_from = start_from
# if start_to is not None:
# report_filter.start_to = start_to
# if end_from is not None:
# report_filter.end_from = end_from
# if end_to is not None:
# report_filter.end_to = end_to
# if process_status is not None:
# report_filter.process_status = process_status.split(",")
# if initiated_by_me is not None:
# report_filter.initiated_by_me = initiated_by_me
# if has_terminal_status is not None:
# report_filter.has_terminal_status = has_terminal_status
# if has_active_status is not None:
# report_filter.has_active_status = has_active_status
# if with_tasks_completed_by_me is not None:
# report_filter.with_tasks_completed_by_me = with_tasks_completed_by_me
# if with_tasks_i_can_complete is not None:
# report_filter.with_tasks_i_can_complete = with_tasks_i_can_complete
# if process_initiator_username is not None:
# report_filter.process_initiator_username = process_initiator_username
# if report_column_list is not None:
# report_filter.report_column_list = report_column_list
# if report_filter_by_list is not None:
# report_filter.report_filter_by_list = report_filter_by_list
# if oldest_open_human_task_fields is not None:
# report_filter.oldest_open_human_task_fields = oldest_open_human_task_fields
# if with_tasks_assigned_to_my_group is not None:
# report_filter.with_tasks_assigned_to_my_group = with_tasks_assigned_to_my_group
# if with_relation_to_me is not None:
# report_filter.with_relation_to_me = with_relation_to_me
#
# return report_filter
@classmethod
def add_metadata_columns_to_process_instance(
cls,
process_instance_sqlalchemy_rows: list[sqlalchemy.engine.row.Row], # type: ignore
metadata_columns: list[dict],
metadata_columns: list[ReportMetadataColumn],
) -> list[dict]:
"""Add_metadata_columns_to_process_instance."""
results = []
non_metadata_columns = cls.non_metadata_columns()
cls.non_metadata_columns()
for process_instance_row in process_instance_sqlalchemy_rows:
process_instance_mapping = process_instance_row._mapping
process_instance_dict = process_instance_row[0].serialized
# import pdb; pdb.set_trace()
for metadata_column in metadata_columns:
# if metadata_column["accessor"] not in non_metadata_columns:
# if metadata_column["accessor"] not in cls.process_instance_stock_columns():
if metadata_column["accessor"] not in process_instance_dict:
# import pdb; pdb.set_trace()
process_instance_dict[metadata_column["accessor"]] = process_instance_mapping[
metadata_column["accessor"]
]
@ -488,12 +295,12 @@ class ProcessInstanceReportService:
@classmethod
def non_metadata_columns(cls) -> list[str]:
return cls.process_instance_stock_columns() + ['process_initiator_username']
return cls.process_instance_stock_columns() + ["process_initiator_username"]
@classmethod
def builtin_column_options(cls) -> list[dict]:
def builtin_column_options(cls) -> list[ReportMetadataColumn]:
"""Builtin_column_options."""
return [
return_value: list[ReportMetadataColumn] = [
{"Header": "Id", "accessor": "id", "filterable": False},
{
"Header": "Process",
@ -509,12 +316,13 @@ class ProcessInstanceReportService:
},
{"Header": "Status", "accessor": "status", "filterable": False},
]
return return_value
@classmethod
def get_filter_value(cls, filters: list[FilterValue], filter_key: str) -> Any:
for filter in filters:
if filter['field_name'] == filter_key and filter['field_value'] is not None:
return filter['field_value']
if filter["field_name"] == filter_key and filter["field_value"] is not None:
return filter["field_value"]
@classmethod
def check_filter_value(cls, filters: list[FilterValue], filter_key: str) -> Generator:
@ -525,9 +333,7 @@ class ProcessInstanceReportService:
@classmethod
def run_process_instance_report(
cls,
# report_filter: ProcessInstanceReportFilter,
report_metadata: ReportMetadata,
process_instance_report: ProcessInstanceReportModel,
user: UserModel,
page: int = 1,
per_page: int = 100,
@ -535,9 +341,9 @@ class ProcessInstanceReportService:
process_instance_query = ProcessInstanceModel.query
# Always join that hot user table for good performance at serialization time.
process_instance_query = process_instance_query.options(selectinload(ProcessInstanceModel.process_initiator))
filters = report_metadata['filter_by']
filters = report_metadata["filter_by"]
for value in cls.check_filter_value(filters, 'process_model_identifier'):
for value in cls.check_filter_value(filters, "process_model_identifier"):
process_model = ProcessModelService.get_process_model(
f"{value}",
)
@ -553,32 +359,24 @@ class ProcessInstanceReportService:
)
)
for value in cls.check_filter_value(filters, 'start_from'):
for value in cls.check_filter_value(filters, "start_from"):
process_instance_query = process_instance_query.filter(ProcessInstanceModel.start_in_seconds >= value)
for value in cls.check_filter_value(filters, "start_to"):
process_instance_query = process_instance_query.filter(ProcessInstanceModel.start_in_seconds <= value)
for value in cls.check_filter_value(filters, "end_from"):
process_instance_query = process_instance_query.filter(ProcessInstanceModel.end_in_seconds >= value)
for value in cls.check_filter_value(filters, "end_to"):
process_instance_query = process_instance_query.filter(ProcessInstanceModel.end_in_seconds <= value)
for value in cls.check_filter_value(filters, "process_status"):
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.start_in_seconds >= value
)
for value in cls.check_filter_value(filters, 'start_to'):
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.start_in_seconds <= value
)
for value in cls.check_filter_value(filters, 'end_from'):
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.end_in_seconds >= value
)
for value in cls.check_filter_value(filters, 'end_to'):
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.end_in_seconds <= value
)
for value in cls.check_filter_value(filters, 'process_status'):
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.in_(value.split(',')) # type: ignore
ProcessInstanceModel.status.in_(value.split(",")) # type: ignore
)
for value in cls.check_filter_value(filters, 'initiated_by_me'):
for value in cls.check_filter_value(filters, "initiated_by_me"):
if value is True:
process_instance_query = process_instance_query.filter_by(process_initiator=user)
for value in cls.check_filter_value(filters, 'has_terminal_status'):
for value in cls.check_filter_value(filters, "has_terminal_status"):
if value is True:
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.in_(ProcessInstanceModel.terminal_statuses()) # type: ignore
@ -587,25 +385,25 @@ class ProcessInstanceReportService:
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.not_in(ProcessInstanceModel.terminal_statuses()) # type: ignore
)
for value in cls.check_filter_value(filters, 'has_active_status'):
for value in cls.check_filter_value(filters, "has_active_status"):
if value is True:
process_instance_query = process_instance_query.filter(
ProcessInstanceModel.status.in_(ProcessInstanceModel.active_statuses()) # type: ignore
)
for value in cls.check_filter_value(filters, 'process_initiator_username'):
for value in cls.check_filter_value(filters, "process_initiator_username"):
initiator = UserModel.query.filter_by(username=value).first()
process_initiator_id = -1
if initiator:
process_initiator_id = initiator.id
process_instance_query = process_instance_query.filter_by(process_initiator_id=process_initiator_id)
with_tasks_completed_by_me = cls.get_filter_value(filters, 'with_tasks_completed_by_me')
with_tasks_assigned_to_my_group = cls.get_filter_value(filters, 'with_tasks_assigned_to_my_group')
with_tasks_i_can_complete = cls.get_filter_value(filters, 'with_tasks_i_can_complete')
with_relation_to_me = cls.get_filter_value(filters, 'with_relation_to_me')
has_active_status = cls.get_filter_value(filters, 'has_active_status')
user_group_identifier = cls.get_filter_value(filters, 'user_group_identifier')
with_tasks_completed_by_me = cls.get_filter_value(filters, "with_tasks_completed_by_me")
with_tasks_assigned_to_my_group = cls.get_filter_value(filters, "with_tasks_assigned_to_my_group")
with_tasks_i_can_complete = cls.get_filter_value(filters, "with_tasks_i_can_complete")
with_relation_to_me = cls.get_filter_value(filters, "with_relation_to_me")
has_active_status = cls.get_filter_value(filters, "has_active_status")
user_group_identifier = cls.get_filter_value(filters, "user_group_identifier")
if (
not with_tasks_completed_by_me
and not with_tasks_assigned_to_my_group
@ -676,27 +474,19 @@ class ProcessInstanceReportService:
process_instance_query = process_instance_query.filter(UserGroupAssignmentModel.user_id == user.id)
instance_metadata_aliases = {}
# print(f"report_metadata['columns']: {report_metadata['columns']}")
# import pdb; pdb.set_trace()
if report_metadata['columns'] and len(report_metadata['columns']) > 0:
process_instance_report.report_metadata["columns"] = report_metadata['columns']
if report_metadata['filter_by'] and len(report_metadata['filter_by']) > 0:
process_instance_report.report_metadata["filter_by"] = report_metadata['filter_by']
if report_metadata["columns"] is None or len(report_metadata["columns"]) < 1:
report_metadata["columns"] = cls.builtin_column_options()
for column in process_instance_report.report_metadata["columns"]:
for column in report_metadata["columns"]:
if column["accessor"] in cls.non_metadata_columns():
continue
instance_metadata_alias = aliased(ProcessInstanceMetadataModel)
instance_metadata_aliases[column["accessor"]] = instance_metadata_alias
filter_for_column = None
if "filter_by" in process_instance_report.report_metadata:
if "filter_by" in report_metadata:
filter_for_column = next(
(
f
for f in process_instance_report.report_metadata["filter_by"]
if f["field_name"] == column["accessor"]
),
(f for f in report_metadata["filter_by"] if f["field_name"] == column["accessor"]),
None,
)
isouter = True
@ -711,41 +501,37 @@ class ProcessInstanceReportService:
instance_metadata_alias, and_(*conditions), isouter=isouter
).add_columns(func.max(instance_metadata_alias.value).label(column["accessor"]))
# order_by_query_array = []
# order_by_array = process_instance_report.report_metadata["order_by"]
# if len(order_by_array) < 1:
# order_by_array = ProcessInstanceReportModel.default_order_by()
# for order_by_option in order_by_array:
# attribute = re.sub("^-", "", order_by_option)
# if attribute in cls.process_instance_stock_columns():
# if order_by_option.startswith("-"):
# order_by_query_array.append(getattr(ProcessInstanceModel, attribute).desc())
# else:
# order_by_query_array.append(getattr(ProcessInstanceModel, attribute).asc())
# elif attribute in instance_metadata_aliases:
# if order_by_option.startswith("-"):
# order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).desc())
# else:
# order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).asc())
order_by_query_array = []
order_by_array = report_metadata["order_by"]
if len(order_by_array) < 1:
order_by_array = ProcessInstanceReportModel.default_order_by()
for order_by_option in order_by_array:
attribute = re.sub("^-", "", order_by_option)
if attribute in cls.process_instance_stock_columns():
if order_by_option.startswith("-"):
order_by_query_array.append(getattr(ProcessInstanceModel, attribute).desc())
else:
order_by_query_array.append(getattr(ProcessInstanceModel, attribute).asc())
elif attribute in instance_metadata_aliases:
if order_by_option.startswith("-"):
order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).desc())
else:
order_by_query_array.append(func.max(instance_metadata_aliases[attribute].value).asc())
process_instances = (
process_instance_query.group_by(ProcessInstanceModel.id)
.add_columns(ProcessInstanceModel.id)
# .order_by(*order_by_query_array)
.order_by(*order_by_query_array)
.paginate(page=page, per_page=per_page, error_out=False)
)
results = cls.add_metadata_columns_to_process_instance(
process_instances.items, process_instance_report.report_metadata["columns"]
)
# import pdb; pdb.set_trace()
results = cls.add_metadata_columns_to_process_instance(process_instances.items, report_metadata["columns"])
for value in cls.check_filter_value(filters, 'oldest_open_human_task_fields'):
for value in cls.check_filter_value(filters, "oldest_open_human_task_fields"):
results = cls.add_human_task_fields(results, value)
response_json = {
"report": process_instance_report,
"report_metadata": report_metadata,
"results": results,
"filters": filters,
"hash": "HEY",
"pagination": {
"count": len(results),
"total": process_instances.total,

View File

@ -8,7 +8,6 @@ from typing import TypedDict
from typing import Union
from uuid import UUID
from flask import current_app
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflow # type: ignore
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer
from SpiffWorkflow.exceptions import WorkflowException # type: ignore
@ -20,7 +19,8 @@ from spiffworkflow_backend.models.bpmn_process import BpmnProcessModel
from spiffworkflow_backend.models.bpmn_process import BpmnProcessNotFoundError
from spiffworkflow_backend.models.bpmn_process_definition import BpmnProcessDefinitionModel
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.json_data import JsonDataDict, JsonDataModel # noqa: F401
from spiffworkflow_backend.models.json_data import JsonDataDict
from spiffworkflow_backend.models.json_data import JsonDataModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventModel
from spiffworkflow_backend.models.process_instance_event import ProcessInstanceEventType

View File

@ -25,9 +25,8 @@ from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_instance_metadata import (
ProcessInstanceMetadataModel,
)
from spiffworkflow_backend.models.process_instance_report import (
ProcessInstanceReportModel,
)
from spiffworkflow_backend.models.process_instance_report import ProcessInstanceReportModel
from spiffworkflow_backend.models.process_instance_report import ReportMetadata
from spiffworkflow_backend.models.process_model import NotificationType
from spiffworkflow_backend.models.process_model import ProcessModelInfoSchema
from spiffworkflow_backend.models.spec_reference import SpecReferenceCache
@ -1975,7 +1974,7 @@ class TestProcessApi(BaseTest):
self.logged_in_headers(with_super_admin_user)
report_identifier = "testreport"
report_metadata = {"order_by": ["month"]}
report_metadata: ReportMetadata = {"order_by": ["month"], "filter_by": [], "columns": []}
ProcessInstanceReportModel.create_with_attributes(
identifier=report_identifier,
report_metadata=report_metadata,
@ -3078,12 +3077,12 @@ class TestProcessApi(BaseTest):
).all()
assert len(process_instance_metadata) == 3
report_metadata = {
report_metadata: ReportMetadata = {
"columns": [
{"Header": "ID", "accessor": "id"},
{"Header": "Status", "accessor": "status"},
{"Header": "Key One", "accessor": "key1"},
{"Header": "Key Two", "accessor": "key2"},
{"Header": "ID", "accessor": "id", "filterable": False},
{"Header": "Status", "accessor": "status", "filterable": False},
{"Header": "Key One", "accessor": "key1", "filterable": False},
{"Header": "Key Two", "accessor": "key2", "filterable": False},
],
"order_by": ["status"],
"filter_by": [],
@ -3130,11 +3129,11 @@ class TestProcessApi(BaseTest):
self.create_process_instance_from_process_model(process_model=process_model, user=user_one)
self.create_process_instance_from_process_model(process_model=process_model, user=with_super_admin_user)
dne_report_metadata = {
dne_report_metadata: ReportMetadata = {
"columns": [
{"Header": "ID", "accessor": "id"},
{"Header": "Status", "accessor": "status"},
{"Header": "Process Initiator", "accessor": "username"},
{"Header": "ID", "accessor": "id", "filterable": False},
{"Header": "Status", "accessor": "status", "filterable": False},
{"Header": "Process Initiator", "accessor": "username", "filterable": False},
],
"order_by": ["status"],
"filter_by": [
@ -3146,11 +3145,11 @@ class TestProcessApi(BaseTest):
],
}
user_one_report_metadata = {
user_one_report_metadata: ReportMetadata = {
"columns": [
{"Header": "ID", "accessor": "id"},
{"Header": "Status", "accessor": "status"},
{"Header": "Process Initiator", "accessor": "username"},
{"Header": "ID", "accessor": "id", "filterable": False},
{"Header": "Status", "accessor": "status", "filterable": False},
{"Header": "Process Initiator", "accessor": "username", "filterable": False},
],
"order_by": ["status"],
"filter_by": [
@ -3308,12 +3307,13 @@ class TestProcessApi(BaseTest):
processor.do_engine_steps(save=True)
assert process_instance_two.status == "complete"
report_metadata = {
report_metadata: ReportMetadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{"Header": "Time", "accessor": "time_ns"},
{"Header": "id", "accessor": "id", "filterable": True},
{"Header": "Time", "accessor": "time_ns", "filterable": True},
],
"order_by": ["time_ns"],
"filter_by": [],
}
report_one = ProcessInstanceReportModel.create_with_attributes(
identifier="report_one",
@ -3333,10 +3333,11 @@ class TestProcessApi(BaseTest):
report_metadata = {
"columns": [
{"Header": "id", "accessor": "id"},
{"Header": "Time", "accessor": "time_ns"},
{"Header": "id", "accessor": "id", "filterable": True},
{"Header": "Time", "accessor": "time_ns", "filterable": True},
],
"order_by": ["-time_ns"],
"filter_by": [],
}
report_two = ProcessInstanceReportModel.create_with_attributes(
identifier="report_two",

View File

@ -362,7 +362,9 @@ class TestProcessInstanceProcessor(BaseTest):
human_task_one = process_instance.active_human_tasks[0]
spiff_manual_task = processor.bpmn_process_instance.get_task_from_id(UUID(human_task_one.task_id))
ProcessInstanceService.complete_form_task(processor, spiff_manual_task, {}, initiator_user, human_task_one)
import pdb; pdb.set_trace()
import pdb
pdb.set_trace()
assert (
len(process_instance.active_human_tasks) == 1
), "expected 1 active human tasks after 2nd one is completed, as we have looped back around."

View File

@ -1,6 +1,4 @@
"""Test_process_instance_report_service."""
from typing import Optional
from flask import Flask
from flask.testing import FlaskClient
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
@ -9,738 +7,13 @@ from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
from spiffworkflow_backend.models.db import db
from spiffworkflow_backend.models.group import GroupModel
from spiffworkflow_backend.models.human_task import HumanTaskModel
from spiffworkflow_backend.models.process_instance_report import (
ProcessInstanceReportModel,
)
from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_report_service import (
ProcessInstanceReportFilter,
)
from spiffworkflow_backend.services.process_instance_report_service import (
ProcessInstanceReportService,
)
from spiffworkflow_backend.services.user_service import UserService
class TestProcessInstanceReportFilter(BaseTest):
"""TestProcessInstanceReportFilter."""
def test_empty_filter_to_dict(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
d = ProcessInstanceReportFilter().to_dict()
assert d == {}
def test_string_value_filter_to_dict(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
d = ProcessInstanceReportFilter(process_model_identifier="bob").to_dict()
assert d == {"process_model_identifier": "bob"}
def test_int_value_filter_to_dict(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
d = ProcessInstanceReportFilter(
start_from=1,
start_to=2,
end_from=3,
end_to=4,
).to_dict()
assert d == {
"start_from": "1",
"start_to": "2",
"end_from": "3",
"end_to": "4",
}
def test_list_single_value_filter_to_dict(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
d = ProcessInstanceReportFilter(process_status=["bob"]).to_dict()
assert d == {"process_status": "bob"}
def test_list_multiple_value_filter_to_dict(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
d = ProcessInstanceReportFilter(process_status=["joe", "bob", "sue"]).to_dict()
assert d == {"process_status": "joe,bob,sue"}
class TestProcessInstanceReportService(BaseTest):
"""TestProcessInstanceReportService."""
def _filter_from_metadata(self, report_metadata: dict) -> ProcessInstanceReportFilter:
"""Docstring."""
report = ProcessInstanceReportModel(
identifier="test",
created_by_id=1,
report_metadata=report_metadata,
)
return ProcessInstanceReportService.filter_from_metadata(report)
def _filter_from_metadata_with_overrides(
self,
report_metadata: dict,
process_model_identifier: Optional[str] = None,
start_from: Optional[int] = None,
start_to: Optional[int] = None,
end_from: Optional[int] = None,
end_to: Optional[int] = None,
process_status: Optional[str] = None,
) -> ProcessInstanceReportFilter:
"""Docstring."""
report = ProcessInstanceReportModel(
identifier="test",
created_by_id=1,
report_metadata=report_metadata,
)
return ProcessInstanceReportService.filter_from_metadata_with_overrides(
process_instance_report=report,
process_model_identifier=process_model_identifier,
start_from=start_from,
start_to=start_to,
end_from=end_from,
end_to=end_to,
process_status=process_status,
)
def _filter_by_dict_from_metadata(self, report_metadata: dict) -> dict[str, str]:
"""Docstring."""
report = ProcessInstanceReportModel(
identifier="test",
created_by_id=1,
report_metadata=report_metadata,
)
return ProcessInstanceReportService.filter_by_to_dict(report)
def test_filter_by_to_dict_no_filter_by(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
filters = self._filter_by_dict_from_metadata(
{
"columns": [],
}
)
assert filters == {}
def test_filter_by_to_dict_empty_filter_by(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
filters = self._filter_by_dict_from_metadata(
{
"columns": [],
"filter_by": [],
}
)
assert filters == {}
def test_filter_by_to_dict_single_filter_by(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
filters = self._filter_by_dict_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "end_to", "field_value": "1234"}],
}
)
assert filters == {"end_to": "1234"}
def test_filter_by_to_dict_mulitple_filter_by(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
filters = self._filter_by_dict_from_metadata(
{
"columns": [],
"filter_by": [
{"field_name": "end_to", "field_value": "1234"},
{"field_name": "end_from", "field_value": "4321"},
],
}
)
assert filters == {"end_to": "1234", "end_from": "4321"}
def test_report_with_no_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_empty_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_unknown_filter_field_name(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "bob", "field_value": "joe"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_unknown_filter_keys(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"_name": "bob", "_value": "joe"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_process_model_identifier_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "process_model_identifier", "field_value": "bob"}],
}
)
assert report_filter.process_model_identifier == "bob"
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_start_from_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "start_from", "field_value": "1234"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from == 1234
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_start_to_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "start_to", "field_value": "1234"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to == 1234
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_end_from_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "end_from", "field_value": "1234"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from == 1234
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_with_end_to_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "end_to", "field_value": "1234"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to == 1234
assert report_filter.process_status is None
def test_report_with_single_startus_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [{"field_name": "process_status", "field_value": "ready"}],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["ready"]
def test_report_with_multiple_startus_filters(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [
{
"field_name": "process_status",
"field_value": "ready,completed,other",
}
],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["ready", "completed", "other"]
def test_report_with_multiple_filters(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata(
{
"columns": [],
"filter_by": [
{"field_name": "start_from", "field_value": "44"},
{"field_name": "end_from", "field_value": "55"},
{"field_name": "process_status", "field_value": "ready"},
],
}
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from == 44
assert report_filter.start_to is None
assert report_filter.end_from == 55
assert report_filter.end_to is None
assert report_filter.process_status == ["ready"]
def test_report_no_override_with_no_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
},
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_override_with_no_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
},
end_to=54321,
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to == 54321
assert report_filter.process_status is None
def test_report_override_process_model_identifier_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "process_model_identifier", "field_value": "bob"}],
},
process_model_identifier="joe",
)
assert report_filter.process_model_identifier == "joe"
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_override_start_from_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "start_from", "field_value": "123"}],
},
start_from=321,
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from == 321
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_override_start_to_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "start_to", "field_value": "123"}],
},
start_to=321,
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to == 321
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_override_end_from_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "end_from", "field_value": "123"}],
},
end_from=321,
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from == 321
assert report_filter.end_to is None
assert report_filter.process_status is None
def test_report_override_end_to_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "end_to", "field_value": "123"}],
},
end_to=321,
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to == 321
assert report_filter.process_status is None
def test_report_override_process_status_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "process_status", "field_value": "joe,bob"}],
},
process_status="sue",
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["sue"]
def test_report_override_mulitple_process_status_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [{"field_name": "process_status", "field_value": "sue"}],
},
process_status="joe,bob",
)
assert report_filter.process_model_identifier is None
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["joe", "bob"]
def test_report_override_does_not_override_other_filters(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [
{"field_name": "process_model_identifier", "field_value": "sue"},
{"field_name": "process_status", "field_value": "sue"},
],
},
process_status="joe,bob",
)
assert report_filter.process_model_identifier == "sue"
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["joe", "bob"]
def test_report_override_of_none_does_not_override_filter(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Docstring."""
report_filter = self._filter_from_metadata_with_overrides(
{
"columns": [],
"filter_by": [
{"field_name": "process_model_identifier", "field_value": "sue"},
{"field_name": "process_status", "field_value": "sue"},
],
},
process_status=None,
)
assert report_filter.process_model_identifier == "sue"
assert report_filter.start_from is None
assert report_filter.start_to is None
assert report_filter.end_from is None
assert report_filter.end_to is None
assert report_filter.process_status == ["sue"]
def test_can_filter_by_completed_instances_initiated_by_me(
self,
app: Flask,
@ -768,13 +41,8 @@ class TestProcessInstanceReportService(BaseTest):
user=user_one,
report_identifier="system_report_completed_instances_initiated_by_me",
)
report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
process_instance_report=process_instance_report,
process_model_identifier=process_model.id,
)
response_json = ProcessInstanceReportService.run_process_instance_report(
report_filter=report_filter,
process_instance_report=process_instance_report,
report_metadata=process_instance_report.report_metadata,
user=user_one,
)
@ -850,13 +118,8 @@ class TestProcessInstanceReportService(BaseTest):
user=user_one,
report_identifier="system_report_completed_instances_with_tasks_completed_by_me",
)
report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
process_instance_report=process_instance_report,
process_model_identifier=process_model.id,
)
response_json = ProcessInstanceReportService.run_process_instance_report(
report_filter=report_filter,
process_instance_report=process_instance_report,
report_metadata=process_instance_report.report_metadata,
user=user_one,
)
@ -936,13 +199,8 @@ class TestProcessInstanceReportService(BaseTest):
user=user_one,
report_identifier="system_report_completed_instances_with_tasks_completed_by_my_groups",
)
report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
process_instance_report=process_instance_report,
process_model_identifier=process_model.id,
)
response_json = ProcessInstanceReportService.run_process_instance_report(
report_filter=report_filter,
process_instance_report=process_instance_report,
report_metadata=process_instance_report.report_metadata,
user=user_one,
)
@ -1026,14 +284,12 @@ class TestProcessInstanceReportService(BaseTest):
UserService.add_user_to_human_tasks_if_appropriate(user_one)
process_instance_report = ProcessInstanceReportService.report_with_identifier(user=user_one)
report_filter = ProcessInstanceReportService.filter_from_metadata_with_overrides(
process_instance_report=process_instance_report,
process_model_identifier=process_model.id,
with_relation_to_me=True,
report_metadata = process_instance_report.report_metadata
report_metadata["filter_by"].append(
{"field_name": "with_relation_to_me", "field_value": True, "operator": "equals"}
)
response_json = ProcessInstanceReportService.run_process_instance_report(
report_filter=report_filter,
process_instance_report=process_instance_report,
report_metadata=report_metadata,
user=user_one,
)

View File

@ -27,6 +27,7 @@ module.exports = {
rules: {
// according to https://github.com/typescript-eslint/typescript-eslint/issues/2621, You should turn off the eslint core rule and turn on the typescript-eslint rule
// but not sure which of the above "extends" statements is maybe bringing in eslint core
'max-len': ['error', { code: 200, ignoreUrls: true }],
'no-shadow': 'off',
'@typescript-eslint/no-shadow': ['error'],
'jest/expect-expect': 'off',

View File

@ -6,27 +6,11 @@ import {
Modal,
// @ts-ignore
} from '@carbon/react';
import {
ReportFilter,
ProcessInstanceReport,
ProcessModel,
ReportColumn,
ReportMetadata,
User,
} from '../interfaces';
import { ProcessInstanceReport, ReportMetadata } from '../interfaces';
import HttpService from '../services/HttpService';
type OwnProps = {
onSuccess: (..._args: any[]) => any;
columnArray: ReportColumn[];
orderBy: string;
processModelSelection: ProcessModel | null;
processInitiatorSelection: User | null;
processStatusSelection: string[];
startFromSeconds: string | null;
startToSeconds: string | null;
endFromSeconds: string | null;
endToSeconds: string | null;
buttonText?: string;
buttonClassName?: string;
processInstanceReportSelection?: ProcessInstanceReport | null;
@ -35,16 +19,7 @@ type OwnProps = {
export default function ProcessInstanceListSaveAsReport({
onSuccess,
columnArray,
orderBy,
processModelSelection,
processInitiatorSelection,
processInstanceReportSelection,
processStatusSelection,
startFromSeconds,
startToSeconds,
endFromSeconds,
endToSeconds,
buttonClassName,
buttonText = 'Save as Perspective',
reportMetadata,
@ -75,74 +50,6 @@ export default function ProcessInstanceListSaveAsReport({
const addProcessInstanceReport = (event: any) => {
event.preventDefault();
// // TODO: make a field to set this
// let orderByArray = ['-start_in_seconds', '-id'];
// if (orderBy) {
// orderByArray = orderBy.split(',').filter((n) => n);
// }
// const filterByArray: any = [];
//
// if (processModelSelection) {
// filterByArray.push({
// field_name: 'process_model_identifier',
// field_value: processModelSelection.id,
// });
// }
//
// if (processInitiatorSelection) {
// filterByArray.push({
// field_name: 'process_initiator_username',
// field_value: processInitiatorSelection.username,
// });
// }
//
// if (processStatusSelection.length > 0) {
// filterByArray.push({
// field_name: 'process_status',
// field_value: processStatusSelection.join(','),
// operator: 'in',
// });
// }
//
// if (startFromSeconds) {
// filterByArray.push({
// field_name: 'start_from',
// field_value: startFromSeconds,
// });
// }
//
// if (startToSeconds) {
// filterByArray.push({
// field_name: 'start_to',
// field_value: startToSeconds,
// });
// }
//
// if (endFromSeconds) {
// filterByArray.push({
// field_name: 'end_from',
// field_value: endFromSeconds,
// });
// }
//
// if (endToSeconds) {
// filterByArray.push({
// field_name: 'end_to',
// field_value: endToSeconds,
// });
// }
//
// reportMetadata.filter_by.forEach((reportFilter: ReportFilter) => {
// columnArray.forEach((reportColumn: ReportColumn) => {
// if (
// reportColumn.accessor === reportFilter.field_name &&
// reportColumn.filterable
// ) {
// filterByArray.push(reportFilter);
// }
// });
// });
let path = `/process-instances/reports`;
let httpMethod = 'POST';
if (isEditMode() && processInstanceReportSelection) {

View File

@ -134,7 +134,6 @@ export default function ProcessInstanceListTable({
const [processInstances, setProcessInstances] = useState([]);
const [reportMetadata, setReportMetadata] = useState<ReportMetadata | null>();
const [pagination, setPagination] = useState<PaginationObject | null>(null);
const [processInstanceFilters, setProcessInstanceFilters] = useState({});
const oneHourInSeconds = 3600;
const oneMonthInSeconds = oneHourInSeconds * 24 * 30;
@ -197,11 +196,10 @@ export default function ProcessInstanceListTable({
const [processInstanceInitiatorOptions, setProcessInstanceInitiatorOptions] =
useState<string[]>([]);
const [processInitiatorSelection, setProcessInitiatorSelection] =
useState<User | null>(null);
const [processInitiatorText, setProcessInitiatorText] = useState<
const [processInitiatorSelection, setProcessInitiatorSelection] = useState<
string | null
>(null);
const [
processInitiatorNotFoundErrorText,
setProcessInitiatorNotFoundErrorText,
@ -232,10 +230,12 @@ export default function ProcessInstanceListTable({
inputText: string
) => {
if (lastRequestedInitatorSearchTerm.current === result.username_prefix) {
setProcessInstanceInitiatorOptions(result.users);
setProcessInstanceInitiatorOptions(
result.users.map((user: User) => user.username)
);
result.users.forEach((user: User) => {
if (user.username === inputText) {
setProcessInitiatorSelection(user);
setProcessInitiatorSelection(user.username);
}
});
}
@ -272,69 +272,46 @@ export default function ProcessInstanceListTable({
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
function setProcessInstancesFromResult(result: any) {
const setProcessInstancesFromResult = useCallback((result: any) => {
setRequiresRefilter(false);
const processInstancesFromApi = result.results;
setProcessInstances(processInstancesFromApi);
setPagination(result.pagination);
setProcessInstanceFilters(result.filters);
setReportMetadata(result.report.report_metadata);
// if (processInstanceReport) {
// if (processInstanceReport.id > 0) {
// setProcessInstanceReportSelection(processInstanceReport);
// }
// }
setReportMetadata(result.report_metadata);
}, []);
const setProcessInstancesFromApplyFilter = (result: any) => {
setProcessInstancesFromResult(result);
if (result.report_hash) {
searchParams.set('report_hash', result.report_hash);
setSearchParams(searchParams);
}
}
};
// Useful to stop refreshing if an api call gets an error
// since those errors can make the page unusable in any way
const clearRefreshRef = useRef<any>(null);
const stopRefreshing = (error: any) => {
const stopRefreshing = useCallback((error: any) => {
if (clearRefreshRef.current) {
clearRefreshRef.current();
}
if (error) {
console.error(error);
}
};
const getData = useCallback(() => {
console.log('WE DO STUFF');
stopRefreshing(null);
}, []);
// eslint-disable-next-line sonarjs/cognitive-complexity
useEffect(() => {
if (!permissionsLoaded) {
return;
return undefined;
}
// we apparently cannot use a state set in a useEffect from within that same useEffect
// so use a variable instead
let processModelSelectionItemsForUseEffect: ProcessModel[] = [];
function setProcessInstancesFromResult(result: any) {
setRequiresRefilter(false);
const processInstancesFromApi = result.results;
setProcessInstances(processInstancesFromApi);
setPagination(result.pagination);
setProcessInstanceFilters(result.filters);
setReportMetadata(result.report.report_metadata);
}
// Useful to stop refreshing if an api call gets an error
// since those errors can make the page unusable in any way
const stopRefreshing = (error: any) => {
if (clearRefreshRef.current) {
clearRefreshRef.current();
}
if (error) {
console.error(error);
}
};
function getProcessInstances(
processInstanceReport: ProcessInstanceReport | null = null
) {
@ -362,7 +339,7 @@ export default function ProcessInstanceListTable({
);
setShowFilterOptions(true);
} else if (reportFilter.field_name === 'process_initiator_username') {
searchForProcessInitiator(reportFilter.field_value || '');
setProcessInitiatorSelection(reportFilter.field_value || '');
setShowFilterOptions(true);
} else if (reportFilter.field_name === 'process_model_identifier') {
selectedProcessModelIdentifier =
@ -416,8 +393,8 @@ export default function ProcessInstanceListTable({
path: `${processInstanceApiSearchPath}?${queryParamString}`,
successCallback: setProcessInstancesFromResult,
httpMethod: 'POST',
failureCallback: getData,
onUnauthorized: getData,
failureCallback: stopRefreshing,
onUnauthorized: stopRefreshing,
postBody: {
report_metadata: reportMetadataBodyToUse,
},
@ -502,62 +479,11 @@ export default function ProcessInstanceListTable({
additionalParams,
processInstanceApiSearchPath,
permissionsLoaded,
listHasBeenFiltered,
setProcessInstancesFromResult,
stopRefreshing,
]);
// // This sets the filter data using the saved reports returned from the initial instance_list query.
// // This could probably be merged into the main useEffect but it works here now.
// useEffect(() => {
// const filters = processInstanceFilters as any;
// // Object.keys(dateParametersToAlwaysFilterBy).forEach((paramName: string) => {
// // const dateFunctionToCall = dateParametersToAlwaysFilterBy[paramName][0];
// // const timeFunctionToCall = dateParametersToAlwaysFilterBy[paramName][1];
// // const paramValue = filters[paramName];
// // dateFunctionToCall('');
// // timeFunctionToCall('');
// // if (paramValue) {
// // const dateString = convertSecondsToFormattedDateString(
// // paramValue as any
// // );
// // dateFunctionToCall(dateString);
// // const timeString = convertSecondsToFormattedTimeHoursMinutes(
// // paramValue as any
// // );
// // timeFunctionToCall(timeString);
// // setShowFilterOptions(true);
// // }
// // });
//
// // setProcessModelSelection(null);
// // processModelAvailableItems.forEach((item: any) => {
// // if (item.id === filters.process_model_identifier) {
// // setProcessModelSelection(item);
// // }
// // });
//
// if (filters.process_initiator_username) {
// const functionToCall =
// parametersToGetFromSearchParams.process_initiator_username;
// functionToCall(filters.process_initiator_username);
// }
//
// const processStatusSelectedArray: string[] = [];
// if (filters.process_status) {
// PROCESS_STATUSES.forEach((processStatusOption: any) => {
// const regex = new RegExp(`\\b${processStatusOption}\\b`);
// if (filters.process_status.match(regex)) {
// processStatusSelectedArray.push(processStatusOption);
// }
// });
// setShowFilterOptions(true);
// }
// // setProcessStatusSelection(processStatusSelectedArray);
// }, [
// processInstanceFilters,
// dateParametersToAlwaysFilterBy,
// parametersToGetFromSearchParams,
// processModelAvailableItems,
// ]);
const processInstanceReportSaveTag = () => {
if (processInstanceReportJustSaved) {
let titleOperation = 'Updated';
@ -656,20 +582,6 @@ export default function ProcessInstanceListTable({
return [];
};
// const reportFilterBy = () => {
// if (reportMetadata) {
// return reportMetadata.filter_by;
// }
// return null
// };
const navigateToNewReport = (queryParamString: string) => {
removeError();
setProcessInstanceReportJustSaved(null);
setProcessInstanceFilters({});
navigate(`${processInstanceListPathPrefix}?${queryParamString}`);
};
const removeFieldFromReportMetadata = (
postBody: ReportMetadata,
fieldName: string
@ -677,21 +589,21 @@ export default function ProcessInstanceListTable({
const filtersToKeep = postBody.filter_by.filter(
(rf: ReportFilter) => rf.field_name !== fieldName
);
// eslint-disable-next-line no-param-reassign
postBody.filter_by = filtersToKeep;
};
const addFieldValueToReportMetadata = (
const insertOrUpdateFieldInReportMetadata = (
postBody: ReportMetadata,
fieldName: string,
fieldValue: string
) => {
removeFieldFromReportMetadata(postBody, fieldName);
if (fieldValue) {
postBody.filter_by.push({
field_name: fieldName,
field_value: fieldValue,
});
} else {
removeFieldFromReportMetadata(postBody, fieldName);
}
};
@ -720,24 +632,29 @@ export default function ProcessInstanceListTable({
};
}
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'start_from',
startFromSeconds
);
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'start_to',
startToSeconds
);
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'end_from',
endFromSeconds
);
addFieldValueToReportMetadata(newReportMetadata, 'end_to', endToSeconds);
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'end_to',
endToSeconds
);
if (processStatusSelection.length > 0) {
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'process_status',
processStatusSelection.join(',')
@ -747,7 +664,7 @@ export default function ProcessInstanceListTable({
}
if (processModelSelection) {
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'process_model_identifier',
processModelSelection.id
@ -760,10 +677,10 @@ export default function ProcessInstanceListTable({
}
if (processInitiatorSelection) {
addFieldValueToReportMetadata(
insertOrUpdateFieldInReportMetadata(
newReportMetadata,
'process_initiator_username',
processInitiatorSelection.username
processInitiatorSelection
);
} else {
removeFieldFromReportMetadata(
@ -800,7 +717,7 @@ export default function ProcessInstanceListTable({
failureCallback: stopRefreshing,
onUnauthorized: stopRefreshing,
successCallback: (result: any) => {
setProcessInstancesFromResult(result);
setProcessInstancesFromApplyFilter(result);
},
});
};
@ -892,7 +809,6 @@ export default function ProcessInstanceListTable({
setEndToDate('');
setEndToTime('');
setProcessInitiatorSelection(null);
setProcessInitiatorText('');
setRequiresRefilter(true);
if (reportMetadata) {
reportMetadata.filter_by = [];
@ -929,35 +845,18 @@ export default function ProcessInstanceListTable({
};
const saveAsReportComponent = () => {
const {
valid,
startFromSeconds,
startToSeconds,
endFromSeconds,
endToSeconds,
} = calculateStartAndEndSeconds(false);
const newReportMetadata = getNewReportMetadataBasedOnPageWidgets();
if (!valid || !reportMetadata || !newReportMetadata) {
if (!newReportMetadata) {
return null;
}
return (
<ProcessInstanceListSaveAsReport
onSuccess={onSaveReportSuccess}
buttonClassName="button-white-background narrow-button"
columnArray={reportColumns()}
orderBy=""
buttonText="Save"
processModelSelection={processModelSelection}
processInitiatorSelection={processInitiatorSelection}
processStatusSelection={processStatusSelection}
processInstanceReportSelection={processInstanceReportSelection}
reportMetadata={newReportMetadata}
startFromSeconds={startFromSeconds}
startToSeconds={startToSeconds}
endFromSeconds={endFromSeconds}
endToSeconds={endToSeconds}
/>
);
};
@ -1325,7 +1224,7 @@ export default function ProcessInstanceListTable({
items={processInstanceInitiatorOptions}
itemToString={(processInstanceInitatorOption: User) => {
if (processInstanceInitatorOption) {
return processInstanceInitatorOption.username;
return processInstanceInitatorOption;
}
return null;
}}
@ -1343,7 +1242,7 @@ export default function ProcessInstanceListTable({
invalid={processInitiatorNotFoundErrorText !== ''}
invalidText={processInitiatorNotFoundErrorText}
onChange={(event: any) => {
setProcessInitiatorText(event.target.value);
setProcessInitiatorSelection(event.target.value);
setRequiresRefilter(true);
}}
/>