Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FWF-3749: [Feature] Application list API changes related to client UI #2533

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"process_name": {"field": "name", "operator": "ilike"},
"process_status": {"field": "status", "operator": "eq"},
"process_type": {"field": "process_type", "operator": "eq"},
"parent_form_id": {"field": "parent_form_id", "operator": "eq"},
}

DEFAULT_PROCESS_KEY = "Defaultflow"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""add-is-draft-column-application-table

Revision ID: 524194732683
Revises: f581ec5971eb
Create Date: 2025-01-17 14:17:56.829145

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '524194732683'
down_revision = 'f581ec5971eb'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('application', sa.Column('is_draft', sa.Boolean(), nullable=True, server_default='false'))
op.create_index(op.f('ix_application_is_draft'), 'application', ['is_draft'], unique=False)
# Update is_draft column in application table to true for active draft applications
update_query = sa.text("""UPDATE public.application
SET is_draft = true
WHERE id IN (SELECT application_id FROM public.draft WHERE status='1');""")
# Execute the SQL statement
op.execute(update_query)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f('ix_application_is_draft'), table_name='application')
op.drop_column('application', 'is_draft')
# ### end Alembic commands ###
2 changes: 1 addition & 1 deletion forms-flow-api/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ ecdsa==0.19.0
flask-jwt-oidc==0.7.0
flask-marshmallow==1.2.1
flask-restx==1.3.0
formsflow_api_utils @ git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#subdirectory=forms-flow-api-utils
formsflow_api_utils @ git+https://github.com/auslin-aot/forms-flow-ai.git@feature/fwf-3749-application-get-api-changes#subdirectory=forms-flow-api-utils
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt this branch be changed to develop during merge? @auslin-aot

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes after merge

gunicorn==23.0.0
h11==0.14.0
h2==4.1.0
Expand Down
2 changes: 1 addition & 1 deletion forms-flow-api/requirements/prod.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ markupsafe
PyJWT
redis
lxml
git+https://github.com/AOT-Technologies/forms-flow-ai.git@develop#subdirectory=forms-flow-api-utils
git+https://github.com/auslin-aot/forms-flow-ai.git@feature/fwf-3749-application-get-api-changes#subdirectory=forms-flow-api-utils
21 changes: 15 additions & 6 deletions forms-flow-api/src/formsflow_api/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from flask_sqlalchemy.query import Query
from formsflow_api_utils.utils import (
DRAFT_APPLICATION_STATUS,
FILTER_MAPS,
validate_sort_order_and_order_by,
)
Expand Down Expand Up @@ -35,6 +34,7 @@ class Application(
latest_form_id = db.Column(db.String(100), nullable=False)
is_resubmit = db.Column(db.Boolean, nullable=True, default=False)
event_name = db.Column(db.String(100), nullable=True)
is_draft = db.Column(db.Boolean, default=False, index=True)

draft = db.relationship(
"Draft", backref=db.backref("Application", cascade="save-update, merge, delete")
Expand All @@ -52,6 +52,7 @@ def create_from_dict(cls, application_info: dict) -> Application:
]
application.submission_id = application_info["submission_id"]
application.latest_form_id = application_info["form_id"]
application.is_draft = application_info.get("is_draft", False)
application.save_and_flush()
return application
return None
Expand All @@ -68,6 +69,7 @@ def update(self, mapper_info: dict):
"modified_by",
"is_resubmit",
"event_name",
"is_draft",
],
mapper_info,
)
Expand Down Expand Up @@ -161,7 +163,7 @@ def filter_conditions(cls, **filters):
filter_map = FILTER_MAPS[key]
model_name = (
Application
if not filter_map["field"] == "form_name"
if filter_map["field"] not in ["form_name", "parent_form_id"]
else FormProcessMapper
)
condition = Application.create_filter_condition(
Expand All @@ -184,10 +186,12 @@ def filter_conditions(cls, **filters):
cls.modified_by,
cls.is_resubmit,
cls.event_name,
cls.is_draft,
FormProcessMapper.form_name.label("application_name"),
FormProcessMapper.process_key.label("process_key"),
FormProcessMapper.process_name.label("process_name"),
FormProcessMapper.process_tenant.label("process_tenant"),
FormProcessMapper.parent_form_id,
)
query = query.filter(*filter_conditions) if filter_conditions else query
return query
Expand All @@ -200,13 +204,18 @@ def find_all_by_user( # pylint: disable=too-many-arguments, too-many-positional
limit: int,
order_by: str,
sort_order: str,
include_drafts: str,
only_drafts: str,
**filters,
) -> Application:
"""Fetch applications list based on searching parameters for Non-reviewer."""
query = cls.filter_conditions(**filters)
query = FormProcessMapper.tenant_authorization(query=query)
query = query.filter(Application.created_by == user_id)
query = cls.filter_draft_applications(query=query)
if only_drafts: # only draft applications
query = query.filter(Application.is_draft.is_(True))
elif not include_drafts: # only submissions
query = cls.filter_draft_applications(query=query)
order_by, sort_order = validate_sort_order_and_order_by(order_by, sort_order)
if order_by and sort_order:
table_name = "application"
Expand Down Expand Up @@ -447,7 +456,7 @@ def find_all_by_form_id_count(cls, form_id: str):
FormProcessMapper, cls.form_process_mapper_id == FormProcessMapper.id
).filter(
cls.latest_form_id == form_id,
cls.application_status != DRAFT_APPLICATION_STATUS,
cls.is_draft.is_(False),
)
return FormProcessMapper.tenant_authorization(query=query).count()

Expand Down Expand Up @@ -695,7 +704,7 @@ def get_total_application_corresponding_to_mapper_id(
FormProcessMapper.id == Application.form_process_mapper_id,
)
.filter(FormProcessMapper.id == form_process_mapper_id)
.filter(Application.application_status != DRAFT_APPLICATION_STATUS)
.filter(Application.is_draft.is_(False))
.one_or_none()
)
# returns a list of one element with count of applications
Expand Down Expand Up @@ -725,7 +734,7 @@ def filter_draft_applications(cls, query: Query):
"""Modifies the query to filter draft applications."""
if not isinstance(query, Query):
raise TypeError("Query object must be of type Query")
return query.filter(cls.application_status != DRAFT_APPLICATION_STATUS)
return query.filter(cls.is_draft.is_(False))

@classmethod
def get_all_application_count(cls):
Expand Down
5 changes: 2 additions & 3 deletions forms-flow-api/src/formsflow_api/models/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import uuid

from formsflow_api_utils.utils import (
DRAFT_APPLICATION_STATUS,
FILTER_MAPS,
validate_sort_order_and_order_by,
)
Expand Down Expand Up @@ -206,7 +205,7 @@ def get_draft_count(cls, **kwargs):
query = query.filter(Application.created_by == user_id)
query = query.filter(
and_(
Application.application_status == DRAFT_APPLICATION_STATUS,
Application.is_draft.is_(True),
Draft.status == str(DraftStatus.ACTIVE.value),
)
)
Expand Down Expand Up @@ -234,7 +233,7 @@ def get_draft_by_parent_form_id(cls, parent_form_id: str) -> Draft:
Application.form_process_mapper_id.in_(
[id for id, in get_all_mapper_id]
),
Application.application_status == DRAFT_APPLICATION_STATUS,
Application.is_draft.is_(True),
)
)
return FormProcessMapper.tenant_authorization(result).all()
110 changes: 70 additions & 40 deletions forms-flow-api/src/formsflow_api/resources/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ class ApplicationsResource(Resource):
"description": "Filter resources by application name.",
"type": "string",
},
"id": {
"Id": {
"in": "query",
"description": "Filter resources by id.",
"type": "int",
Expand All @@ -145,6 +145,46 @@ class ApplicationsResource(Resource):
"description": "Filter resources by modified to.",
"type": "string",
},
"createdBy": {
"in": "query",
"description": "Filter resources by created by.",
"type": "string",
},
"createdFrom": {
"in": "query",
"description": "Filter resources by created from.",
"type": "string",
},
"createdTo": {
"in": "query",
"description": "Filter resources by created to.",
"type": "string",
},
"applicationStatus": {
"in": "query",
"description": "Filter resources by application status.",
"type": "string",
},
"parentFormId": {
"in": "query",
"description": "Filter resources by parent form id.",
"type": "string",
},
"createdUserSubmissions": {
"in": "query",
"description": "Return user created submissions.",
"type": "bool",
},
"includeDrafts": {
"in": "query",
"description": "Return submissions and drafts/Specific to client permission.",
"type": "bool",
},
"onlyDrafts": {
"in": "query",
"description": "Return only drafts/Specific to client permission.",
"type": "bool",
},
}
)
@API.response(200, "OK:- Successful request.", model=application_list_model)
Expand All @@ -159,64 +199,54 @@ class ApplicationsResource(Resource):
def get(): # pylint:disable=too-many-locals
"""Get applications."""
dict_data = ApplicationListRequestSchema().load(request.args) or {}
page_no = dict_data.get("page_no")
limit = dict_data.get("limit")
order_by = dict_data.get("order_by", "id")
application_id = dict_data.get("application_id")
application_name = dict_data.get("application_name")
application_status = dict_data.get("application_status")
created_by = dict_data.get("created_by")
created_from_date = dict_data.get("created_from_date")
created_to_date = dict_data.get("created_to_date")
modified_from_date = dict_data.get("modified_from_date")
modified_to_date = dict_data.get("modified_to_date")
sort_order = dict_data.get("sort_order", "desc")
if auth.has_role([VIEW_TASKS, MANAGE_TASKS]):
# Common parameters
common_filters = {
"page_no": dict_data.get("page_no"),
"limit": dict_data.get("limit"),
"order_by": dict_data.get("order_by", "id"),
"application_id": dict_data.get("application_id"),
"application_name": dict_data.get("application_name"),
"application_status": dict_data.get("application_status"),
"created_by": dict_data.get("created_by"),
"created_from": dict_data.get("created_from_date"),
"created_to": dict_data.get("created_to_date"),
"modified_from": dict_data.get("modified_from_date"),
"modified_to": dict_data.get("modified_to_date"),
"sort_order": dict_data.get("sort_order", "desc"),
"parent_form_id": dict_data.get("parent_form_id"),
}

# Flags
include_drafts = dict_data.get("include_drafts", False)
only_drafts = dict_data.get("only_drafts", False)
created_user_submissions = dict_data.get("created_user_submissions", False)

if auth.has_role([VIEW_TASKS, MANAGE_TASKS]) and not created_user_submissions:
(
application_schema_dump,
application_count,
draft_count,
) = ApplicationService.get_auth_applications_and_count(
created_from=created_from_date,
created_to=created_to_date,
modified_from=modified_from_date,
modified_to=modified_to_date,
order_by=order_by,
sort_order=sort_order,
created_by=created_by,
application_id=application_id,
application_name=application_name,
application_status=application_status,
page_no=page_no,
limit=limit,
filters=common_filters
)
else:
(
application_schema_dump,
application_count,
draft_count,
) = ApplicationService.get_all_applications_by_user(
page_no=page_no,
limit=limit,
order_by=order_by,
sort_order=sort_order,
created_from=created_from_date,
created_to=created_to_date,
modified_from=modified_from_date,
modified_to=modified_to_date,
created_by=created_by,
application_id=application_id,
application_name=application_name,
application_status=application_status,
filters=common_filters,
include_drafts=include_drafts,
only_drafts=only_drafts,
)
return (
(
{
"applications": application_schema_dump,
"totalCount": application_count,
"draftCount": draft_count,
"limit": limit,
"pageNo": page_no,
"limit": common_filters["limit"],
"pageNo": common_filters["page_no"],
}
),
HTTPStatus.OK,
Expand Down
5 changes: 5 additions & 0 deletions forms-flow-api/src/formsflow_api/schemas/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class ApplicationListRequestSchema(ApplicationListReqSchema):
data_key="modifiedTo", format="%Y-%m-%dT%H:%M:%S+00:00"
)
sort_order = fields.Str(data_key="sortOrder", required=False)
created_user_submissions = fields.Bool(data_key="createdUserSubmissions")
parent_form_id = fields.Str(data_key="parentFormId")
include_drafts = fields.Bool(data_key="includeDrafts")
only_drafts = fields.Bool(data_key="onlyDrafts")


class ApplicationSchema(AuditDateTimeSchema):
Expand Down Expand Up @@ -66,6 +70,7 @@ class Meta: # pylint: disable=too-few-public-methods
is_resubmit = fields.Bool(data_key="isResubmit", dump_only=True)
event_name = fields.Str(data_key="eventName", dump_only=True)
data = fields.Dict(data_key="data", load_only=True)
is_draft = fields.Bool(data_key="isDraft", dump_only=True)


class ApplicationUpdateSchema(Schema):
Expand Down
Loading
Loading