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/4d75421c0af0_.py b/spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py similarity index 98% rename from spiffworkflow-backend/migrations/versions/4d75421c0af0_.py rename to spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py index 34fa1e97..5e018dd0 100644 --- a/spiffworkflow-backend/migrations/versions/4d75421c0af0_.py +++ b/spiffworkflow-backend/migrations/versions/90dcaa99faa7_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 4d75421c0af0 +Revision ID: 90dcaa99faa7 Revises: -Create Date: 2022-12-06 17:42:56.417673 +Create Date: 2022-12-16 16:40:22.246123 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '4d75421c0af0' +revision = '90dcaa99faa7' down_revision = None branch_labels = None depends_on = None @@ -189,12 +189,14 @@ def upgrade(): sa.Column('task_type', sa.String(length=50), nullable=True), sa.Column('task_status', sa.String(length=50), nullable=True), sa.Column('process_model_display_name', sa.String(length=255), nullable=True), + sa.Column('completed', sa.Boolean(), nullable=False), sa.ForeignKeyConstraint(['actual_owner_id'], ['user.id'], ), sa.ForeignKeyConstraint(['lane_assignment_id'], ['group.id'], ), sa.ForeignKeyConstraint(['process_instance_id'], ['process_instance.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('task_id', 'process_instance_id', name='active_task_unique') ) + op.create_index(op.f('ix_active_task_completed'), 'active_task', ['completed'], unique=False) op.create_table('message_correlation', sa.Column('id', sa.Integer(), nullable=False), sa.Column('process_instance_id', sa.Integer(), nullable=False), @@ -304,6 +306,7 @@ def downgrade(): op.drop_index(op.f('ix_message_correlation_name'), table_name='message_correlation') op.drop_index(op.f('ix_message_correlation_message_correlation_property_id'), table_name='message_correlation') op.drop_table('message_correlation') + op.drop_index(op.f('ix_active_task_completed'), table_name='active_task') op.drop_table('active_task') op.drop_table('user_group_assignment') op.drop_table('secret') diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py index ea9e1055..37c751ea 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/models/active_task.py @@ -52,6 +52,7 @@ class ActiveTaskModel(SpiffworkflowBaseDBModel): task_type: str = db.Column(db.String(50)) task_status: str = db.Column(db.String(50)) process_model_display_name: str = db.Column(db.String(255)) + completed: bool = db.Column(db.Boolean, default=False, nullable=False, index=True) active_task_users = relationship("ActiveTaskUserModel", cascade="delete") potential_owners = relationship( # type: ignore 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 aff7a9c0..1724ab73 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/routes/process_api_blueprint.py @@ -940,7 +940,12 @@ def process_instance_list( print(f"report_filter.with_relation_to_me: {report_filter.with_relation_to_me}") if report_filter.with_relation_to_me is True: - process_instance_query = process_instance_query.outerjoin(ActiveTaskModel).outerjoin(ActiveTaskUserModel, ActiveTaskUserModel.user_id == g.user.id) + process_instance_query = process_instance_query.outerjoin(ActiveTaskModel).outerjoin(ActiveTaskUserModel, + and_( + ActiveTaskModel.id == ActiveTaskUserModel.active_task_id, + ActiveTaskUserModel.user_id == g.user.id, + ), + ) process_instance_query = process_instance_query.filter(or_(ActiveTaskUserModel.id.is_not(None), ProcessInstanceModel.process_initiator_id == g.user.id)) if report_filter.initiated_by_me is True: @@ -1417,6 +1422,7 @@ def get_tasks( .outerjoin(GroupModel, GroupModel.id == ActiveTaskModel.lane_assignment_id) .join(ProcessInstanceModel) .join(UserModel, UserModel.id == ProcessInstanceModel.process_initiator_id) + .filter(ActiveTaskModel.completed == False) ) if processes_started_by_user: @@ -1451,19 +1457,23 @@ def get_tasks( else: active_tasks_query = active_tasks_query.filter(ActiveTaskModel.lane_assignment_id.is_(None)) # type: ignore - active_tasks = active_tasks_query.add_columns( - ProcessInstanceModel.process_model_identifier, - ProcessInstanceModel.status.label("process_instance_status"), # type: ignore - ProcessInstanceModel.updated_at_in_seconds, - ProcessInstanceModel.created_at_in_seconds, - UserModel.username, - GroupModel.identifier.label("group_identifier"), - ActiveTaskModel.task_name, - ActiveTaskModel.task_title, - ActiveTaskModel.process_model_display_name, - ActiveTaskModel.process_instance_id, - ActiveTaskUserModel.user_id.label("current_user_is_potential_owner"), - ).paginate(page=page, per_page=per_page, error_out=False) + active_tasks = ( + active_tasks_query.add_columns( + ProcessInstanceModel.process_model_identifier, + ProcessInstanceModel.status.label("process_instance_status"), # type: ignore + ProcessInstanceModel.updated_at_in_seconds, + ProcessInstanceModel.created_at_in_seconds, + UserModel.username, + GroupModel.identifier.label("group_identifier"), + ActiveTaskModel.task_name, + ActiveTaskModel.task_title, + ActiveTaskModel.process_model_display_name, + ActiveTaskModel.process_instance_id, + ActiveTaskUserModel.user_id.label("current_user_is_potential_owner"), + ) + .order_by(desc(ActiveTaskModel.id)) # type: ignore + .paginate(page=page, per_page=per_page, error_out=False) + ) response_json = { "results": active_tasks.items, @@ -1683,7 +1693,7 @@ def task_submit( spiff_task.terminate_loop() active_task = ActiveTaskModel.query.filter_by( - process_instance_id=process_instance_id, task_id=task_id + process_instance_id=process_instance_id, task_id=task_id, completed=False ).first() if active_task is None: raise ( @@ -1713,7 +1723,7 @@ def task_submit( # next_task = processor.next_task() next_active_task_assigned_to_me = ( - ActiveTaskModel.query.filter_by(process_instance_id=process_instance_id) + ActiveTaskModel.query.filter_by(process_instance_id=process_instance_id, completed=False) .order_by(asc(ActiveTaskModel.id)) # type: ignore .join(ActiveTaskUserModel) .filter_by(user_id=principal.user_id) diff --git a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py index 3ad3fbe7..e8f97d03 100644 --- a/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py +++ b/spiffworkflow-backend/src/spiffworkflow_backend/services/process_instance_processor.py @@ -699,10 +699,11 @@ class ProcessInstanceProcessor: db.session.add(active_task_user) db.session.commit() - # if len(active_tasks) > 0: - # for at in active_tasks: - # db.session.delete(at) - # db.session.commit() + if len(active_tasks) > 0: + for at in active_tasks: + at.completed = True + db.session.add(at) + db.session.commit() @staticmethod def get_parser() -> MyCustomParser: diff --git a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx index 1d75db56..af4dfe8f 100644 --- a/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessInstanceList.tsx @@ -39,7 +39,7 @@ export default function ProcessInstanceList() { <> {processInstanceBreadcrumbElement()} {processInstanceTitleElement()} - + ); } diff --git a/spiffworkflow-frontend/src/routes/TaskShow.tsx b/spiffworkflow-frontend/src/routes/TaskShow.tsx index 3412dcef..2fc6ffcc 100644 --- a/spiffworkflow-frontend/src/routes/TaskShow.tsx +++ b/spiffworkflow-frontend/src/routes/TaskShow.tsx @@ -171,7 +171,6 @@ export default function TaskShow() { } else if (taskToUse.form_ui_schema) { formUiSchema = JSON.parse(taskToUse.form_ui_schema); } - if (taskToUse.state !== 'READY') { formUiSchema = Object.assign(formUiSchema || {}, { 'ui:readonly': true, @@ -184,7 +183,7 @@ export default function TaskShow() { reactFragmentToHideSubmitButton =
; } - if (taskToUse.type === 'Manual Task') { + if (taskToUse.type === 'Manual Task' && taskToUse.state === 'READY') { reactFragmentToHideSubmitButton = (