From 41945900c13959e2e68b16203c7c022e8b62ed10 Mon Sep 17 00:00:00 2001 From: auslin-aot <99173163+auslin-aot@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:52:17 +0530 Subject: [PATCH 1/4] FWF-3749: [Feature] Application list api changes related to client --- .../formsflow_api_utils/utils/constants.py | 1 + ...3_add_is_draft_column_application_table.py | 36 +++++++++++++++++++ forms-flow-api/requirements.txt | 2 +- forms-flow-api/requirements/prod.txt | 2 +- .../src/formsflow_api/models/application.py | 16 +++++++-- .../formsflow_api/resources/application.py | 11 +++++- .../src/formsflow_api/schemas/application.py | 5 +++ .../src/formsflow_api/services/application.py | 8 +++++ .../src/formsflow_api/services/draft.py | 5 ++- 9 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 forms-flow-api/migrations/versions/524194732683_add_is_draft_column_application_table.py diff --git a/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py b/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py index 08b2396b6a..05d28cd490 100644 --- a/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py +++ b/forms-flow-api-utils/src/formsflow_api_utils/utils/constants.py @@ -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" diff --git a/forms-flow-api/migrations/versions/524194732683_add_is_draft_column_application_table.py b/forms-flow-api/migrations/versions/524194732683_add_is_draft_column_application_table.py new file mode 100644 index 0000000000..3006aadc4a --- /dev/null +++ b/forms-flow-api/migrations/versions/524194732683_add_is_draft_column_application_table.py @@ -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 ### diff --git a/forms-flow-api/requirements.txt b/forms-flow-api/requirements.txt index 50daee26df..a3b2ee3c8b 100644 --- a/forms-flow-api/requirements.txt +++ b/forms-flow-api/requirements.txt @@ -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 gunicorn==23.0.0 h11==0.14.0 h2==4.1.0 diff --git a/forms-flow-api/requirements/prod.txt b/forms-flow-api/requirements/prod.txt index 2e0fa6b0d5..8b9eb2ae12 100644 --- a/forms-flow-api/requirements/prod.txt +++ b/forms-flow-api/requirements/prod.txt @@ -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 diff --git a/forms-flow-api/src/formsflow_api/models/application.py b/forms-flow-api/src/formsflow_api/models/application.py index 15a317aaed..57308f4cfa 100644 --- a/forms-flow-api/src/formsflow_api/models/application.py +++ b/forms-flow-api/src/formsflow_api/models/application.py @@ -35,6 +35,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") @@ -52,6 +53,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 @@ -68,6 +70,7 @@ def update(self, mapper_info: dict): "modified_by", "is_resubmit", "event_name", + "is_draft", ], mapper_info, ) @@ -161,7 +164,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( @@ -184,10 +187,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 @@ -200,13 +205,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" @@ -725,7 +735,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): diff --git a/forms-flow-api/src/formsflow_api/resources/application.py b/forms-flow-api/src/formsflow_api/resources/application.py index f991a317d4..f17dcc5a01 100644 --- a/forms-flow-api/src/formsflow_api/resources/application.py +++ b/forms-flow-api/src/formsflow_api/resources/application.py @@ -171,7 +171,12 @@ def get(): # pylint:disable=too-many-locals 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]): + created_user_submissions = dict_data.get("created_user_submissions", False) + parent_form_id = dict_data.get("parent_form_id") + include_drafts = dict_data.get("include_drafts") + only_drafts = dict_data.get("only_drafts") + + if auth.has_role([VIEW_TASKS, MANAGE_TASKS]) and not created_user_submissions: ( application_schema_dump, application_count, @@ -189,6 +194,7 @@ def get(): # pylint:disable=too-many-locals application_status=application_status, page_no=page_no, limit=limit, + parent_form_id=parent_form_id, ) else: ( @@ -208,6 +214,9 @@ def get(): # pylint:disable=too-many-locals application_id=application_id, application_name=application_name, application_status=application_status, + parent_form_id=parent_form_id, + include_drafts=include_drafts, + only_drafts=only_drafts, ) return ( ( diff --git a/forms-flow-api/src/formsflow_api/schemas/application.py b/forms-flow-api/src/formsflow_api/schemas/application.py index 588e500d95..278c766494 100644 --- a/forms-flow-api/src/formsflow_api/schemas/application.py +++ b/forms-flow-api/src/formsflow_api/schemas/application.py @@ -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): @@ -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): diff --git a/forms-flow-api/src/formsflow_api/services/application.py b/forms-flow-api/src/formsflow_api/services/application.py index 98c21c0131..6c3da99396 100644 --- a/forms-flow-api/src/formsflow_api/services/application.py +++ b/forms-flow-api/src/formsflow_api/services/application.py @@ -197,6 +197,7 @@ def get_auth_applications_and_count( # pylint: disable=too-many-arguments,too-m application_status: str, created_by: str, sort_order: str, + parent_form_id: str, **kwargs, ): """Get applications only from authorized groups.""" @@ -230,6 +231,7 @@ def get_auth_applications_and_count( # pylint: disable=too-many-arguments,too-m created_to=created_to, form_ids=form_ids, user_name=user_name, + parent_form_id=parent_form_id, ) draft_count = Draft.get_draft_count() return ( @@ -280,6 +282,9 @@ def get_all_applications_by_user( # pylint: disable=too-many-arguments,too-many application_status: str, application_name: str, application_id: int, + parent_form_id: str, + include_drafts: str, + only_drafts: bool, **kwargs, ): """Get all applications based on user.""" @@ -299,6 +304,9 @@ def get_all_applications_by_user( # pylint: disable=too-many-arguments,too-many modified_to=modified_to, created_from=created_from, created_to=created_to, + parent_form_id=parent_form_id, + include_drafts=include_drafts, + only_drafts=only_drafts, ) draft_count = Draft.get_draft_count() return ( diff --git a/forms-flow-api/src/formsflow_api/services/draft.py b/forms-flow-api/src/formsflow_api/services/draft.py index 7fe685bef7..5f6ae55455 100644 --- a/forms-flow-api/src/formsflow_api/services/draft.py +++ b/forms-flow-api/src/formsflow_api/services/draft.py @@ -55,6 +55,7 @@ def create_new_draft(cls, application_payload, draft_payload, token=None, **kwar application_payload["application_status"] = DRAFT_APPLICATION_STATUS application_payload["submission_id"] = None + application_payload["is_draft"] = True application = cls.__create_draft_application(application_payload) if not application: raise BusinessException(BusinessErrorCode.APPLICATION_CREATE_ERROR) @@ -129,10 +130,12 @@ def make_submission_from_draft(data: Dict, draft_id: str, token=None, **kwargs): application = Application.find_by_id(draft.application_id) mapper = FormProcessMapper.find_form_by_form_id(application.latest_form_id) + update_dict = {"is_draft": False} if application.form_process_mapper_id != mapper.id: # The form mapper version got updated after the draft entry # was created, update the application with new mapper - application.update({"form_process_mapper_id": mapper.id}) + update_dict["form_process_mapper_id"] = mapper.id + application.update(update_dict) task_variables = ( json.loads(mapper.task_variable) if mapper.task_variable is not None From 725f7390ec7244cf17d7e41a4cf08b9a1817e34b Mon Sep 17 00:00:00 2001 From: auslin-aot <99173163+auslin-aot@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:06:19 +0530 Subject: [PATCH 2/4] FWF-3749: [Feature] Sonar fix and api docs update --- .../src/formsflow_api/models/application.py | 5 +- .../src/formsflow_api/models/draft.py | 5 +- .../formsflow_api/resources/application.py | 109 +++++++++++------- .../src/formsflow_api/services/application.py | 80 +++++-------- 4 files changed, 96 insertions(+), 103 deletions(-) diff --git a/forms-flow-api/src/formsflow_api/models/application.py b/forms-flow-api/src/formsflow_api/models/application.py index 57308f4cfa..7285be8711 100644 --- a/forms-flow-api/src/formsflow_api/models/application.py +++ b/forms-flow-api/src/formsflow_api/models/application.py @@ -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, ) @@ -457,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() @@ -705,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 diff --git a/forms-flow-api/src/formsflow_api/models/draft.py b/forms-flow-api/src/formsflow_api/models/draft.py index 38ee44723a..639babd7a7 100644 --- a/forms-flow-api/src/formsflow_api/models/draft.py +++ b/forms-flow-api/src/formsflow_api/models/draft.py @@ -5,7 +5,6 @@ import uuid from formsflow_api_utils.utils import ( - DRAFT_APPLICATION_STATUS, FILTER_MAPS, validate_sort_order_and_order_by, ) @@ -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), ) ) @@ -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() diff --git a/forms-flow-api/src/formsflow_api/resources/application.py b/forms-flow-api/src/formsflow_api/resources/application.py index f17dcc5a01..d62dfeb02b 100644 --- a/forms-flow-api/src/formsflow_api/resources/application.py +++ b/forms-flow-api/src/formsflow_api/resources/application.py @@ -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", @@ -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) @@ -159,22 +199,27 @@ 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") + # 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) - parent_form_id = dict_data.get("parent_form_id") - include_drafts = dict_data.get("include_drafts") - only_drafts = dict_data.get("only_drafts") if auth.has_role([VIEW_TASKS, MANAGE_TASKS]) and not created_user_submissions: ( @@ -182,19 +227,7 @@ def get(): # pylint:disable=too-many-locals 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, - parent_form_id=parent_form_id, + filters=common_filters ) else: ( @@ -202,19 +235,7 @@ def get(): # pylint:disable=too-many-locals 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, - parent_form_id=parent_form_id, + filters=common_filters, include_drafts=include_drafts, only_drafts=only_drafts, ) @@ -224,8 +245,8 @@ def get(): # pylint:disable=too-many-locals "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, diff --git a/forms-flow-api/src/formsflow_api/services/application.py b/forms-flow-api/src/formsflow_api/services/application.py index 6c3da99396..dff23e03b6 100644 --- a/forms-flow-api/src/formsflow_api/services/application.py +++ b/forms-flow-api/src/formsflow_api/services/application.py @@ -182,22 +182,29 @@ def _application_access(token: str) -> bool: resource_list, ) + @staticmethod + def extract_common_filters(filters: dict) -> dict: + """Extract common filter parameters from the filters dictionary.""" + return { + "application_id": filters.get("application_id"), + "application_name": filters.get("application_name"), + "application_status": filters.get("application_status"), + "created_by": filters.get("created_by"), + "page_no": filters.get("page_no"), + "limit": filters.get("limit"), + "order_by": filters.get("order_by"), + "sort_order": filters.get("sort_order"), + "created_from": filters.get("created_from"), + "created_to": filters.get("created_to"), + "modified_from": filters.get("modified_from"), + "modified_to": filters.get("modified_to"), + "parent_form_id": filters.get("parent_form_id"), + } + @staticmethod @user_context def get_auth_applications_and_count( # pylint: disable=too-many-arguments,too-many-locals,too-many-positional-arguments - page_no: int, - limit: int, - order_by: str, - created_from: datetime, - created_to: datetime, - modified_from: datetime, - modified_to: datetime, - application_id: int, - application_name: str, - application_status: str, - created_by: str, - sort_order: str, - parent_form_id: str, + filters: dict, **kwargs, ): """Get applications only from authorized groups.""" @@ -213,25 +220,15 @@ def get_auth_applications_and_count( # pylint: disable=too-many-arguments,too-m ) for form in forms: form_ids.append(form.resource_id) + + common_filters = ApplicationService.extract_common_filters(filters) ( applications, get_all_applications_count, ) = Application.find_applications_by_auth_formids_user( - application_id=application_id, - application_name=application_name, - application_status=application_status, - created_by=created_by, - page_no=page_no, - limit=limit, - order_by=order_by, - modified_from=modified_from, - modified_to=modified_to, - sort_order=sort_order, - created_from=created_from, - created_to=created_to, + **common_filters, form_ids=form_ids, user_name=user_name, - parent_form_id=parent_form_id, ) draft_count = Draft.get_draft_count() return ( @@ -270,41 +267,18 @@ def get_auth_by_application_id(application_id: int, **kwargs): @staticmethod @user_context def get_all_applications_by_user( # pylint: disable=too-many-arguments,too-many-locals,too-many-positional-arguments - page_no: int, - limit: int, - order_by: str, - sort_order: str, - created_from: datetime, - created_to: datetime, - modified_from: datetime, - modified_to: datetime, - created_by: str, - application_status: str, - application_name: str, - application_id: int, - parent_form_id: str, - include_drafts: str, + filters: dict, + include_drafts: bool, only_drafts: bool, **kwargs, ): """Get all applications based on user.""" user: UserContext = kwargs["user"] user_id: str = user.user_name + common_filters = ApplicationService.extract_common_filters(filters) applications, get_all_applications_count = Application.find_all_by_user( user_id=user_id, - page_no=page_no, - limit=limit, - order_by=order_by, - sort_order=sort_order, - application_id=application_id, - application_name=application_name, - application_status=application_status, - created_by=created_by, - modified_from=modified_from, - modified_to=modified_to, - created_from=created_from, - created_to=created_to, - parent_form_id=parent_form_id, + **common_filters, include_drafts=include_drafts, only_drafts=only_drafts, ) From 32d887678bdf38f885aa2872b6bc936380a36f6e Mon Sep 17 00:00:00 2001 From: auslin-aot <99173163+auslin-aot@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:07:12 +0530 Subject: [PATCH 3/4] FWF-3749: [Feature] Testcase added --- .../tests/unit/api/test_application.py | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/forms-flow-api/tests/unit/api/test_application.py b/forms-flow-api/tests/unit/api/test_application.py index d99febcae2..50cd9008b4 100644 --- a/forms-flow-api/tests/unit/api/test_application.py +++ b/forms-flow-api/tests/unit/api/test_application.py @@ -143,6 +143,44 @@ def test_application_list_with_no_draft( assert response.status_code == 200 assert len(response.json["applications"]) == 0 + def test_application_list_include_drafts_and_only_drafts( + self, app, client, session, jwt, create_mapper + ): + """Test Application list with includeDrafts & onlyDrafts query param.""" + form_id = create_mapper["formId"] + token = get_token(jwt, role=CREATE_SUBMISSIONS) + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + # creating application + rv = client.post( + "/application/create", + headers=headers, + json=get_application_create_payload(form_id), + ) + + assert rv.status_code == 201 + # creating a draft + client.post("/draft", headers=headers, json=get_draft_create_payload(form_id)) + token = get_token(jwt, role=VIEW_SUBMISSIONS) + headers = { + "Authorization": f"Bearer {token}", + "content-type": "application/json", + } + # With includeDrafts=true, includes drafts in-addition to submissions + response = client.get("/application?includeDrafts=true", headers=headers) + assert response.status_code == 200 + assert len(response.json["applications"]) == 2 + # With includeDrafts=false, returns only submissions + response = client.get("/application?includeDrafts=false", headers=headers) + assert response.status_code == 200 + assert len(response.json["applications"]) == 1 + # With onlyDrafts=true, application list api returns only drafts + response = client.get("/application?onlyDrafts=true", headers=headers) + assert response.status_code == 200 + assert len(response.json["applications"]) == 1 + class TestApplicationDetailView: """Test suite for the API/application/ endpoint.""" From 14734a7786a597fab0b48eebf59b03d36e7bc109 Mon Sep 17 00:00:00 2001 From: auslin-aot <99173163+auslin-aot@users.noreply.github.com> Date: Tue, 21 Jan 2025 10:49:27 +0530 Subject: [PATCH 4/4] FWF-3749: [Feature] Added changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39e612df2d..e0b70c6810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,19 @@ Mark items as `Added`, `Changed`, `Fixed`, `Modified`, `Removed`, `Untested Features`, `Upcoming Features`, `Known Issues` +## 7.1.0 + +`Added` + +**formsflow-api** +* Below fields added to application list endpoint + * Added parentFormId filter parameter to filter the submissions for a specific form + * Added the includeDrafts parameter to include drafts along with submissions. + * Added the onlyDrafts parameter to retrieve only drafts. + * Added the createdUserSubmissions parameter to filter submissions created by a specific user. +* Added a new column, is_draft, to the application table to identify draft entries. +* Added Alembic script to update existing active drafts by setting is_draft to true in the application table. +* Added the includeSubmissionsCount=true parameter to the form list endpoint to include the submissions count. ## 7.0.0 - 2025-01-10