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()}
-