added api call to get active tasks w/ burnettk

This commit is contained in:
jasquat 2022-06-28 17:11:10 -04:00
parent 89a0904b5d
commit 17a2c19227
10 changed files with 108 additions and 15 deletions

View File

@ -1,5 +1,3 @@
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: 86938cb17c3d Revision ID: a650f4061955
Revises: Revises:
Create Date: 2022-06-28 14:21:54.294238 Create Date: 2022-06-28 15:15:08.319053
""" """
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 = '86938cb17c3d' revision = 'a650f4061955'
down_revision = None down_revision = None
branch_labels = None branch_labels = None
depends_on = None depends_on = None
@ -93,7 +93,7 @@ def upgrade():
sa.Column('task_id', sa.String(length=50), nullable=False), sa.Column('task_id', sa.String(length=50), nullable=False),
sa.Column('process_instance_id', sa.Integer(), nullable=False), sa.Column('process_instance_id', sa.Integer(), nullable=False),
sa.Column('assigned_principal_id', sa.Integer(), nullable=True), sa.Column('assigned_principal_id', sa.Integer(), nullable=True),
sa.Column('task_data', sa.Text(), nullable=True), sa.Column('process_instance_data', sa.Text(), nullable=True),
sa.Column('status', sa.String(length=50), nullable=False), sa.Column('status', sa.String(length=50), nullable=False),
sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True), sa.Column('updated_at_in_seconds', sa.Integer(), nullable=True),
sa.Column('created_at_in_seconds', sa.Integer(), nullable=True), sa.Column('created_at_in_seconds', sa.Integer(), nullable=True),

View File

@ -552,6 +552,34 @@ paths:
# '204': # '204':
# description: The file was removed. # description: The file was removed.
/tasks/my-tasks:
parameters:
- name: page
in: query
required: false
description: The page number to return. Defaults to page 1.
schema:
type: integer
- name: per_page
in: query
required: false
description: The page number to return. Defaults to page 1.
schema:
type: integer
get:
operationId: spiffworkflow_backend.routes.process_api_blueprint.task_list_my_tasks
summary: returns the list of ready or waiting tasks for a user
responses:
"200":
description: list of tasks
content:
application/json:
schema:
type: array
items:
# $ref: "#/components/schemas/ActiveTask"
$ref: "#/components/schemas/Task"
components: components:
securitySchemes: securitySchemes:
jwt: jwt:

View File

@ -3,6 +3,7 @@ from typing import Any
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
@ -14,4 +15,10 @@ def find_or_create_user(username: str = "test_user1") -> Any:
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
principal = PrincipalModel.query.filter_by(user_id=user.id).first()
if principal is None:
principal = PrincipalModel(user_id=user.id)
db.session.add(principal)
db.session.commit()
return user return user

View File

@ -4,6 +4,7 @@ autoflake8 will remove these lines without the noqa comment
""" """
from flask_bpmn.models.db import add_listeners from flask_bpmn.models.db import add_listeners
from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401
from spiffworkflow_backend.models.data_store import DataStoreModel # noqa: F401 from spiffworkflow_backend.models.data_store import DataStoreModel # noqa: F401
from spiffworkflow_backend.models.file import FileModel # noqa: F401 from spiffworkflow_backend.models.file import FileModel # noqa: F401
from spiffworkflow_backend.models.principal import PrincipalModel # noqa: F401 from spiffworkflow_backend.models.principal import PrincipalModel # noqa: F401
@ -14,7 +15,6 @@ from spiffworkflow_backend.models.process_instance_report import (
ProcessInstanceReportModel, ProcessInstanceReportModel,
) # noqa: F401 ) # noqa: F401
from spiffworkflow_backend.models.task_event import TaskEventModel # noqa: F401 from spiffworkflow_backend.models.task_event import TaskEventModel # noqa: F401
from spiffworkflow_backend.models.active_task import ActiveTaskModel # noqa: F401
from spiffworkflow_backend.models.user import UserModel # noqa: F401 from spiffworkflow_backend.models.user import UserModel # noqa: F401
from spiffworkflow_backend.models.user_group_assignment import ( from spiffworkflow_backend.models.user_group_assignment import (
UserGroupAssignmentModel, UserGroupAssignmentModel,

View File

@ -1,28 +1,31 @@
"""Active_task.""" """Active_task."""
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from flask_bpmn.models.db import SpiffworkflowBaseDBModel from flask_bpmn.models.db import SpiffworkflowBaseDBModel
from sqlalchemy import ForeignKey from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.principal import PrincipalModel
@dataclass
class ActiveTaskModel(SpiffworkflowBaseDBModel): class ActiveTaskModel(SpiffworkflowBaseDBModel):
"""ActiveTaskModel.""" """ActiveTaskModel."""
__tablename__ = "active_task" __tablename__ = "active_task"
__table_args__ = ( __table_args__ = (
db.UniqueConstraint("task_id", "process_instance_id", name="active_task_unique"), db.UniqueConstraint(
"task_id", "process_instance_id", name="active_task_unique"
),
) )
id: int = db.Column(db.Integer, primary_key=True) id: int = db.Column(db.Integer, primary_key=True)
task_id: str = db.Column(db.String(50), nullable=False) task_id: str = db.Column(db.String(50), nullable=False)
process_instance_id: int = db.Column(db.Integer, nullable=False) process_instance_id: int = db.Column(db.Integer, nullable=False)
assigned_principal_id: int = db.Column(ForeignKey(PrincipalModel.id)) assigned_principal_id: int = db.Column(ForeignKey(PrincipalModel.id))
assigned_principal: relationship(PrincipalModel) process_instance_data: str = db.Column(db.Text)
task_data: str = db.Column(db.Text)
status: str = db.Column(db.String(50), nullable=False) status: str = db.Column(db.String(50), nullable=False)
updated_at_in_seconds: int = db.Column(db.Integer) updated_at_in_seconds: int = db.Column(db.Integer)

View File

@ -15,5 +15,5 @@ class PrincipalModel(SpiffworkflowBaseDBModel):
__table_args__ = (CheckConstraint("NOT(user_id IS NULL AND group_id IS NULL)"),) __table_args__ = (CheckConstraint("NOT(user_id IS NULL AND group_id IS NULL)"),)
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(ForeignKey(UserModel.id), nullable=True) user_id = db.Column(ForeignKey(UserModel.id), nullable=True, unique=True)
group_id = db.Column(ForeignKey(GroupModel.id), nullable=True) group_id = db.Column(ForeignKey(GroupModel.id), nullable=True, unique=True)

View File

@ -12,6 +12,7 @@ from flask import url_for
from flask_bpmn.models.db import db from flask_bpmn.models.db import db
from werkzeug.wrappers.response import Response from werkzeug.wrappers.response import Response
from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.user import UserModel from spiffworkflow_backend.models.user import UserModel
from spiffworkflow_backend.services.process_instance_processor import ( from spiffworkflow_backend.services.process_instance_processor import (
ProcessInstanceProcessor, ProcessInstanceProcessor,
@ -41,6 +42,12 @@ def token() -> str:
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
principal = PrincipalModel.query.filter_by(user_id=user.id).first()
if principal is None:
principal = PrincipalModel(user_id=user.id)
db.session.add(principal)
db.session.commit()
auth_token = user.encode_auth_token() auth_token = user.encode_auth_token()
return f"auth_token: {auth_token}" return f"auth_token: {auth_token}"

View File

@ -16,6 +16,7 @@ from flask_bpmn.models.db import db
from spiffworkflow_backend.exceptions.process_entity_not_found_error import ( from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
ProcessEntityNotFoundError, ProcessEntityNotFoundError,
) )
from spiffworkflow_backend.models.active_task import ActiveTaskModel
from spiffworkflow_backend.models.file import FileSchema from spiffworkflow_backend.models.file import FileSchema
from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.principal import PrincipalModel from spiffworkflow_backend.models.principal import PrincipalModel
@ -430,6 +431,35 @@ def process_instance_report(
return Response(json.dumps(response_json), status=200, mimetype="application/json") return Response(json.dumps(response_json), status=200, mimetype="application/json")
def task_list_my_tasks(page: int = 1, per_page: int = 100) -> flask.wrappers.Response:
"""Task_list_my_tasks."""
principal = PrincipalModel.query.filter_by(user_id=g.user.id).first()
if principal is None:
raise (
ApiError(
code="principal_not_found",
message=f"Principal not found from user id: {g.user.id}",
status_code=400,
)
)
active_tasks = (
ActiveTaskModel.query.filter_by(assigned_principal_id=principal.id)
.order_by(ActiveTaskModel.id.desc())
.paginate(page, per_page, False)
)
response_json = {
"results": active_tasks.items,
"pagination": {
"count": len(active_tasks.items),
"total": active_tasks.total,
"pages": active_tasks.pages,
},
}
return response_json
def get_file_from_request() -> Any: def get_file_from_request() -> Any:
"""Get_file_from_request.""" """Get_file_from_request."""
request_file = connexion.request.files.get("file") request_file = connexion.request.files.get("file")

View File

@ -30,10 +30,12 @@ from SpiffWorkflow.dmn.serializer import BusinessRuleTaskConverter # type: igno
from SpiffWorkflow.exceptions import WorkflowTaskExecException # type: ignore from SpiffWorkflow.exceptions import WorkflowTaskExecException # type: ignore
from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore from SpiffWorkflow.serializer.exceptions import MissingSpecError # type: ignore
from SpiffWorkflow.specs import WorkflowSpec # type: ignore from SpiffWorkflow.specs import WorkflowSpec # type: ignore
from SpiffWorkflow.task import Task # type: ignore from SpiffWorkflow.task import Task
from spiffworkflow_backend.models.active_task import ActiveTaskModel # type: ignore
from spiffworkflow_backend.models.file import File from spiffworkflow_backend.models.file import File
from spiffworkflow_backend.models.file import FileType from spiffworkflow_backend.models.file import FileType
from spiffworkflow_backend.models.principal import PrincipalModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
from spiffworkflow_backend.models.process_model import ProcessModelInfo from spiffworkflow_backend.models.process_model import ProcessModelInfo
@ -331,6 +333,19 @@ class ProcessInstanceProcessor:
self.process_instance_model.end_in_seconds = round(time.time()) self.process_instance_model.end_in_seconds = round(time.time())
db.session.add(self.process_instance_model) db.session.add(self.process_instance_model)
ready_or_waiting_tasks = self.get_all_ready_or_waiting_tasks()
for ready_or_waiting_task in ready_or_waiting_tasks:
active_task = ActiveTaskModel(
task_id=str(ready_or_waiting_task.id),
process_instance_id=self.process_instance_model.id,
# FIXME: look for the correct principal based on ready_or_waiting_task.lane
assigned_principal_id=PrincipalModel.query.first().id,
process_instance_data=json.dumps(self.get_data()),
status=ready_or_waiting_task.state.value,
)
db.session.add(active_task)
db.session.commit() db.session.commit()
@staticmethod @staticmethod
@ -555,6 +570,11 @@ class ProcessInstanceProcessor:
and t.state in [TaskState.COMPLETED, TaskState.CANCELLED] and t.state in [TaskState.COMPLETED, TaskState.CANCELLED]
] ]
def get_all_ready_or_waiting_tasks(self) -> list[Task]:
"""Get_all_ready_or_waiting_tasks."""
all_tasks = self.bpmn_process_instance.get_tasks(TaskState.ANY_MASK)
return [t for t in all_tasks if t.state in [TaskState.WAITING, TaskState.READY]]
def get_nav_item(self, task: Task) -> Any: def get_nav_item(self, task: Task) -> Any:
"""Get_nav_item.""" """Get_nav_item."""
for nav_item in self.bpmn_process_instance.get_nav_list(): for nav_item in self.bpmn_process_instance.get_nav_list():