From 2fc44907e80a6f41a1c057dc98e79b37af2628d8 Mon Sep 17 00:00:00 2001 From: jasquat Date: Tue, 29 Nov 2022 17:32:29 -0500 Subject: [PATCH] added api to get list of process report columns --- spiffworkflow-backend/migrations/env.py | 2 + .../{ff1c1628337c_.py => 40a2ed63cc5a_.py} | 8 ++-- .../src/spiffworkflow_backend/api.yml | 16 ++++++++ .../models/process_instance_metadata.py | 2 +- .../routes/process_api_blueprint.py | 9 +++++ .../process_instance_report_service.py | 14 +++++++ .../integration/test_process_api.py | 38 ++++++++++++++++++- 7 files changed, 83 insertions(+), 6 deletions(-) rename spiffworkflow-backend/migrations/versions/{ff1c1628337c_.py => 40a2ed63cc5a_.py} (98%) diff --git a/spiffworkflow-backend/migrations/env.py b/spiffworkflow-backend/migrations/env.py index 630e381a..68feded2 100644 --- a/spiffworkflow-backend/migrations/env.py +++ b/spiffworkflow-backend/migrations/env.py @@ -1,3 +1,5 @@ +from __future__ import with_statement + import logging from logging.config import fileConfig diff --git a/spiffworkflow-backend/migrations/versions/ff1c1628337c_.py b/spiffworkflow-backend/migrations/versions/40a2ed63cc5a_.py similarity index 98% rename from spiffworkflow-backend/migrations/versions/ff1c1628337c_.py rename to spiffworkflow-backend/migrations/versions/40a2ed63cc5a_.py index d8da6d3c..6abd6b4a 100644 --- a/spiffworkflow-backend/migrations/versions/ff1c1628337c_.py +++ b/spiffworkflow-backend/migrations/versions/40a2ed63cc5a_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: ff1c1628337c +Revision ID: 40a2ed63cc5a Revises: -Create Date: 2022-11-28 15:08:52.014254 +Create Date: 2022-11-29 16:59:02.980181 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = 'ff1c1628337c' +revision = '40a2ed63cc5a' down_revision = None branch_labels = None depends_on = None @@ -249,6 +249,7 @@ def upgrade(): sa.PrimaryKeyConstraint('id'), 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', sa.Column('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_table('active_task_user') 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('permission_assignment') op.drop_table('message_instance') diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml index e7dc00fe..81fa92bd 100755 --- a/spiffworkflow-backend/src/spiffworkflow_backend/api.yml +++ b/spiffworkflow-backend/src/spiffworkflow_backend/api.yml @@ -841,6 +841,22 @@ paths: schema: $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}: parameters: - name: report_identifier diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py index 5a4d4ca5..c9003594 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/process_instance_metadata.py @@ -23,7 +23,7 @@ class ProcessInstanceMetadataModel(SpiffworkflowBaseDBModel): process_instance_id: int = db.Column( 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) updated_at_in_seconds: int = db.Column(db.Integer, nullable=False) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py index b3bc1a22..b96cc262 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -977,6 +977,15 @@ def process_instance_list( 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( modified_process_model_identifier: str, process_instance_id: int ) -> flask.wrappers.Response: diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py index ad9dec0a..da70f0c0 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_report_service.py @@ -268,3 +268,17 @@ class ProcessInstanceReportService: def get_column_names_for_model(cls, model: db.Model) -> list[str]: # type: ignore """Get_column_names_for_model.""" 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"}, + ] diff --git a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py index e22ec77b..beef3b74 100644 --- a/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/spiffworkflow-backend/tests/spiffworkflow_backend/integration/test_process_api.py @@ -2577,7 +2577,7 @@ class TestProcessApi(BaseTest): {"Header": "ID", "accessor": "id"}, {"Header": "Status", "accessor": "status"}, {"Header": "Key One", "accessor": "key1"}, - # {"Header": "Key Two", "accessor": "key2"}, + {"Header": "Key Two", "accessor": "key2"}, ], "order_by": ["status"], "filter_by": [], @@ -2600,7 +2600,41 @@ class TestProcessApi(BaseTest): assert response.json["results"][0]["status"] == "complete" assert response.json["results"][0]["id"] == process_instance.id 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"]["pages"] == 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'}] +