added api to get list of process report columns

This commit is contained in:
jasquat 2022-11-29 17:32:29 -05:00
parent 5cd7abc18f
commit 258b478954
7 changed files with 83 additions and 6 deletions

View File

@ -1,3 +1,5 @@
from __future__ import with_statement
import logging import logging
from logging.config import fileConfig from logging.config import fileConfig

View File

@ -1,8 +1,8 @@
"""empty message """empty message
Revision ID: ff1c1628337c Revision ID: 40a2ed63cc5a
Revises: Revises:
Create Date: 2022-11-28 15:08:52.014254 Create Date: 2022-11-29 16:59:02.980181
""" """
from alembic import op from alembic import op
@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic. # revision identifiers, used by Alembic.
revision = 'ff1c1628337c' revision = '40a2ed63cc5a'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -249,6 +249,7 @@ def upgrade():
sa.PrimaryKeyConstraint('id'), sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('process_instance_id', 'key', name='process_instance_metadata_unique') sa.UniqueConstraint('process_instance_id', 'key', name='process_instance_metadata_unique')
) )
op.create_index(op.f('ix_process_instance_metadata_key'), 'process_instance_metadata', ['key'], unique=False)
op.create_table('spiff_step_details', op.create_table('spiff_step_details',
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False), sa.Column('process_instance_id', sa.Integer(), nullable=False),
@ -295,6 +296,7 @@ def downgrade():
op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user') op.drop_index(op.f('ix_active_task_user_active_task_id'), table_name='active_task_user')
op.drop_table('active_task_user') op.drop_table('active_task_user')
op.drop_table('spiff_step_details') op.drop_table('spiff_step_details')
op.drop_index(op.f('ix_process_instance_metadata_key'), table_name='process_instance_metadata')
op.drop_table('process_instance_metadata') op.drop_table('process_instance_metadata')
op.drop_table('permission_assignment') op.drop_table('permission_assignment')
op.drop_table('message_instance') op.drop_table('message_instance')

View File

@ -841,6 +841,22 @@ paths:
schema: schema:
$ref: "#/components/schemas/OkTrue" $ref: "#/components/schemas/OkTrue"
/process-instances/reports/columns:
get:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_instance_report_column_list
summary: Returns all available columns for a process instance report.
tags:
- Process Instances
responses:
"200":
description: Workflow.
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Workflow"
/process-instances/reports/{report_identifier}: /process-instances/reports/{report_identifier}:
parameters: parameters:
- name: report_identifier - name: report_identifier

View File

@ -23,7 +23,7 @@ class ProcessInstanceMetadataModel(SpiffworkflowBaseDBModel):
process_instance_id: int = db.Column( process_instance_id: int = db.Column(
ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore ForeignKey(ProcessInstanceModel.id), nullable=False # type: ignore
) )
key: str = db.Column(db.String(255), nullable=False) key: str = db.Column(db.String(255), nullable=False, index=True)
value: str = db.Column(db.String(255), nullable=False) value: str = db.Column(db.String(255), nullable=False)
updated_at_in_seconds: int = db.Column(db.Integer, nullable=False) updated_at_in_seconds: int = db.Column(db.Integer, nullable=False)

View File

@ -977,6 +977,15 @@ def process_instance_list(
return make_response(jsonify(response_json), 200) return make_response(jsonify(response_json), 200)
def process_instance_report_column_list() -> flask.wrappers.Response:
table_columns = ProcessInstanceReportService.builtin_column_options()
columns_for_metadata = db.session.query(ProcessInstanceMetadataModel.key).distinct().all() # type: ignore
columns_for_metadata_strings = [{ 'Header': i[0], 'accessor': i[0]} for i in columns_for_metadata]
# columns = sorted(table_columns + columns_for_metadata_strings)
return make_response(jsonify(table_columns + columns_for_metadata_strings), 200)
def process_instance_show( def process_instance_show(
modified_process_model_identifier: str, process_instance_id: int modified_process_model_identifier: str, process_instance_id: int
) -> flask.wrappers.Response: ) -> flask.wrappers.Response:

View File

@ -268,3 +268,17 @@ class ProcessInstanceReportService:
def get_column_names_for_model(cls, model: db.Model) -> list[str]: # type: ignore def get_column_names_for_model(cls, model: db.Model) -> list[str]: # type: ignore
"""Get_column_names_for_model.""" """Get_column_names_for_model."""
return [i.name for i in model.__table__.columns] return [i.name for i in model.__table__.columns]
@classmethod
def builtin_column_options(cls) -> list[dict]:
return [
{"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": "username", "accessor": "username"},
{"Header": "status", "accessor": "status"},
]

View File

@ -2577,7 +2577,7 @@ class TestProcessApi(BaseTest):
{"Header": "ID", "accessor": "id"}, {"Header": "ID", "accessor": "id"},
{"Header": "Status", "accessor": "status"}, {"Header": "Status", "accessor": "status"},
{"Header": "Key One", "accessor": "key1"}, {"Header": "Key One", "accessor": "key1"},
# {"Header": "Key Two", "accessor": "key2"}, {"Header": "Key Two", "accessor": "key2"},
], ],
"order_by": ["status"], "order_by": ["status"],
"filter_by": [], "filter_by": [],
@ -2600,7 +2600,41 @@ class TestProcessApi(BaseTest):
assert response.json["results"][0]["status"] == "complete" assert response.json["results"][0]["status"] == "complete"
assert response.json["results"][0]["id"] == process_instance.id assert response.json["results"][0]["id"] == process_instance.id
assert response.json["results"][0]["key1"] == "value1" assert response.json["results"][0]["key1"] == "value1"
# assert response.json["results"][0]["key2"] == "value2" assert response.json["results"][0]["key2"] == "value2"
assert response.json["pagination"]["count"] == 1 assert response.json["pagination"]["count"] == 1
assert response.json["pagination"]["pages"] == 1 assert response.json["pagination"]["pages"] == 1
assert response.json["pagination"]["total"] == 1 assert response.json["pagination"]["total"] == 1
def test_can_get_process_instance_report_column_list(
self,
app: Flask,
client: FlaskClient,
with_db_and_bpmn_file_cleanup: None,
with_super_admin_user: UserModel,
) -> None:
"""Test_can_get_process_instance_list_with_report_metadata."""
process_model = load_test_spec(
process_model_id="test-process-instance-metadata-report",
bpmn_file_name="process_instance_metadata.bpmn",
process_model_source_directory="test-process-instance-metadata-report",
)
process_instance = self.create_process_instance_from_process_model(
process_model=process_model, user=with_super_admin_user
)
processor = ProcessInstanceProcessor(process_instance)
processor.do_engine_steps(save=True)
process_instance_metadata = ProcessInstanceMetadataModel.query.filter_by(
process_instance_id=process_instance.id
).all()
assert len(process_instance_metadata) == 2
response = client.get(
f"/v1.0/process-instances/reports/columns",
headers=self.logged_in_headers(with_super_admin_user),
)
assert response.json is not None
assert response.status_code == 200
assert response.json == [{'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': 'username', 'accessor': 'username'}, {'Header': 'status', 'accessor': 'status'}, {'Header': 'key1', 'accessor': 'key1'}, {'Header': 'key2', 'accessor': 'key2'}]