From b98609eb6b129ce79397f3d0ae2af3871e0e094c Mon Sep 17 00:00:00 2001 From: ivan koryshkin Date: Wed, 5 Jun 2024 17:28:47 +0400 Subject: [PATCH 1/3] fix(summary-activities) Filter deleted and turned into assessment activities without answers --- src/apps/answers/service.py | 13 +++++- src/apps/answers/tests/conftest.py | 51 ++++++++++++++++++++++++ src/apps/answers/tests/test_answers.py | 46 +++++++++++++++++++++ src/apps/applets/crud/applets_history.py | 8 ++++ 4 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/apps/answers/service.py b/src/apps/answers/service.py index 9f6d86a1c87..960d41bfb95 100644 --- a/src/apps/answers/service.py +++ b/src/apps/answers/service.py @@ -71,7 +71,7 @@ ) from apps.answers.filters import AppletSubmitDateFilter, ReviewAppletItemFilter, SummaryActivityFilter from apps.answers.tasks import create_report -from apps.applets.crud import AppletsCRUD +from apps.applets.crud import AppletHistoriesCRUD, AppletsCRUD from apps.applets.domain.applet_history import Version from apps.applets.domain.base import Encryption from apps.applets.service import AppletHistoryService @@ -1030,6 +1030,7 @@ async def get_summary_activities( self, applet_id: uuid.UUID, filters: SummaryActivityFilter ) -> list[SummaryActivity]: assert self.user_id + current_applet_version = await AppletHistoriesCRUD(self.session).get_current_versions_by_applet_id(applet_id) act_hst_crud = ActivityHistoriesCRUD(self.session) activities = await act_hst_crud.get_last_histories_by_applet(applet_id=applet_id) activity_ver_ids = [activity.id_version for activity in activities] @@ -1043,11 +1044,21 @@ async def get_summary_activities( submitted_activities[activity_id] = max(submit_date, date) if date else submit_date submitted_activities[activity_history_id] = submit_date + current_activity_histories = await act_hst_crud.retrieve_by_applet_version(current_applet_version) + current_activities_map = {str(ah.id): ah for ah in current_activity_histories} results = [] for activity in activities: activity_history_answer_date = submitted_activities.get( activity.id_version, submitted_activities.get(str(activity.id)) ) + has_answer = bool(activity_history_answer_date) + if not has_answer: + activity_curr = current_activities_map.get(str(activity.id)) + if not activity_curr: + continue + elif activity_curr.is_reviewable: + continue + results.append( SummaryActivity( id=activity.id, diff --git a/src/apps/answers/tests/conftest.py b/src/apps/answers/tests/conftest.py index 5bc0e9e5111..96e91ed12a4 100644 --- a/src/apps/answers/tests/conftest.py +++ b/src/apps/answers/tests/conftest.py @@ -474,3 +474,54 @@ async def editor_user_reviewer_applet_one(user: UserSchema, session: AsyncSessio applet_id = uuid.UUID("92917a56-d586-4613-b7aa-991f2c4b15b1") srv = UserAppletAccessService(session, user.id, applet_id) await srv.add_role(user.id, Role.EDITOR) + + +@pytest.fixture +async def applet__activity_turned_into_assessment( + session: AsyncSession, tom: User, applet_data: AppletCreate +) -> AppletFull: + """ + Applet with one Activity0 updated into applet with Activity0(is_reviewable=True) and Activity1 + All activities has no answers + """ + srv = AppletService(session, tom.id) + applet = await srv.create(applet_data) + data = AppletUpdate(**applet.dict()) + + activity_new = data.activities[0].copy(deep=True) + activity_new.id = uuid.uuid4() + activity_new.key = uuid.uuid4() + for i in range(len(activity_new.items)): + activity_new.items[i].id = uuid.uuid4() + activity_new.name = "New activity" + data.activities.append(activity_new) + + data.activities[0].is_reviewable = True + data.activities[0].name = "Reviewer assessment" + srv = AppletService(session, tom.id) + updated_applet = await srv.update(applet.id, data) + return updated_applet + + +@pytest.fixture +async def applet__deleted_activity_without_answers( + session: AsyncSession, tom: User, applet_data: AppletCreate +) -> AppletFull: + """ + Applet with one Activity0 updated into applet with Activity1 and deleted Activity1 + All activities has no answers + """ + srv = AppletService(session, tom.id) + applet = await srv.create(applet_data) + data = AppletUpdate(**applet.dict()) + + activity_new = data.activities[0].copy(deep=True) + activity_new.id = uuid.uuid4() + activity_new.key = uuid.uuid4() + for i in range(len(activity_new.items)): + activity_new.items[i].id = uuid.uuid4() + activity_new.name = "New activity" + data.activities = [activity_new] + srv = AppletService(session, tom.id) + updated_applet = await srv.update(applet.id, data) + return updated_applet diff --git a/src/apps/answers/tests/test_answers.py b/src/apps/answers/tests/test_answers.py index aca099ee7ab..293cb050991 100644 --- a/src/apps/answers/tests/test_answers.py +++ b/src/apps/answers/tests/test_answers.py @@ -1888,3 +1888,49 @@ async def test_access_to_activity_list( client.login(user) response = await client.get(url) assert response.status_code == expected + + async def test_get_summary_activities_no_answer_no_empty_deleted_history( + self, client: TestClient, tom: User, applet: AppletFull + ): + client.login(tom) + + response = await client.get( + self.summary_activities_url.format( + applet_id=str(applet.id), + ) + ) + + assert response.status_code == http.HTTPStatus.OK + assert response.json()["count"] == 1 + assert response.json()["result"][0]["name"] == applet.activities[0].name + assert response.json()["result"][0]["id"] == str(applet.activities[0].id) + assert not response.json()["result"][0]["isPerformanceTask"] + assert not response.json()["result"][0]["hasAnswer"] + + async def test_activity_turned_into_assessment_not_included_in_list( + self, client: TestClient, tom: User, applet__activity_turned_into_assessment: AppletFull + ): + client.login(tom) + response = await client.get( + self.summary_activities_url.format( + applet_id=str(applet__activity_turned_into_assessment.id), + ) + ) + + assert response.status_code == http.HTTPStatus.OK + assert response.json()["count"] == 1 + assert response.json()["result"][0]["id"] == str(applet__activity_turned_into_assessment.activities[1].id) + + async def test_deleted_activity_without_answers_not_included_in_list( + self, client: TestClient, tom: User, applet__deleted_activity_without_answers + ): + client.login(tom) + response = await client.get( + self.summary_activities_url.format( + applet_id=str(applet__deleted_activity_without_answers.id), + ) + ) + + assert response.status_code == http.HTTPStatus.OK + assert response.json()["count"] == 1 + assert response.json()["result"][0]["id"] == str(applet__deleted_activity_without_answers.activities[0].id) diff --git a/src/apps/applets/crud/applets_history.py b/src/apps/applets/crud/applets_history.py index e208c19625b..702eb71515a 100644 --- a/src/apps/applets/crud/applets_history.py +++ b/src/apps/applets/crud/applets_history.py @@ -77,3 +77,11 @@ async def set_report_configuration( query = query.values(**schema.dict(by_alias=False)) await self._execute(query) + + async def get_current_versions_by_applet_id(self, applet_id: uuid.UUID) -> str: + query: Query = select(AppletHistorySchema.id_version) + query = query.where(AppletHistorySchema.id == applet_id) + query = query.order_by(AppletHistorySchema.created_at.desc()) + query = query.limit(1) + result = await self._execute(query) + return result.scalars().first() From 3a66a7f54eadef57909fb5ffb7f8ec3501bd50ed Mon Sep 17 00:00:00 2001 From: ivan koryshkin Date: Wed, 5 Jun 2024 18:22:01 +0400 Subject: [PATCH 2/3] fix(summary-activities) Filter deleted flows without answers --- src/apps/activity_flows/crud/flow_history.py | 8 ++++++++ src/apps/answers/service.py | 7 +++++++ src/apps/answers/tests/conftest.py | 17 +++++++++++++++-- src/apps/answers/tests/test_answers.py | 14 +++++++++++++- 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/apps/activity_flows/crud/flow_history.py b/src/apps/activity_flows/crud/flow_history.py index 647e97852c7..f9c128601e7 100644 --- a/src/apps/activity_flows/crud/flow_history.py +++ b/src/apps/activity_flows/crud/flow_history.py @@ -112,3 +112,11 @@ async def get_versions_data(self, flow_id: uuid.UUID) -> list[Version]: data = result.all() return parse_obj_as(list[Version], data) + + async def get_by_applet_version(self, applet_id_version: str) -> list[ActivityFlowHistoriesSchema]: + query: Query = select(ActivityFlowHistoriesSchema) + query = query.where(ActivityFlowHistoriesSchema.applet_id == applet_id_version) + query = query.join(AppletHistorySchema, AppletHistorySchema.id_version == ActivityFlowHistoriesSchema.applet_id) + query = query.order_by(AppletHistorySchema.created_at.desc()) + result = await self._execute(query) + return result.scalars().all() diff --git a/src/apps/answers/service.py b/src/apps/answers/service.py index 960d41bfb95..8901a4d7083 100644 --- a/src/apps/answers/service.py +++ b/src/apps/answers/service.py @@ -1074,6 +1074,7 @@ async def get_summary_activity_flows( self, applet_id: uuid.UUID, target_subject_id: uuid.UUID | None ) -> list[SummaryActivityFlow]: assert self.user_id + current_applet_version = await AppletHistoriesCRUD(self.session).get_current_versions_by_applet_id(applet_id) flow_crud = FlowsHistoryCRUD(self.session) answer_crud = AnswersCRUD(self.answer_session) flow_history_ids_with_date = await answer_crud.get_submitted_flows_with_last_date(applet_id, target_subject_id) @@ -1086,11 +1087,17 @@ async def get_summary_activity_flows( submitted_activity_flows[flow_id] = max(submit_date, date) if date else submit_date submitted_activity_flows[version_id] = submit_date + flow_histories = await flow_crud.get_by_applet_version(current_applet_version) + flow_histories_curr = [flow_h.id for flow_h in flow_histories] results = [] for flow_history in activity_flow_histories: flow_history_answer_date = submitted_activity_flows.get( flow_history.id_version, submitted_activity_flows.get(str(flow_history.id)) ) + has_answer = bool(flow_history_answer_date) + if not has_answer and flow_history.id not in flow_histories_curr: + continue + results.append( SummaryActivityFlow( id=flow_history.id, diff --git a/src/apps/answers/tests/conftest.py b/src/apps/answers/tests/conftest.py index 96e91ed12a4..bf1a1a72c76 100644 --- a/src/apps/answers/tests/conftest.py +++ b/src/apps/answers/tests/conftest.py @@ -498,7 +498,6 @@ async def applet__activity_turned_into_assessment( data.activities[0].is_reviewable = True data.activities[0].name = "Reviewer assessment" - srv = AppletService(session, tom.id) updated_applet = await srv.update(applet.id, data) return updated_applet @@ -522,6 +521,20 @@ async def applet__deleted_activity_without_answers( activity_new.items[i].id = uuid.uuid4() activity_new.name = "New activity" data.activities = [activity_new] - srv = AppletService(session, tom.id) updated_applet = await srv.update(applet.id, data) return updated_applet + + +@pytest.fixture +async def applet__deleted_flow_without_answers( + session: AsyncSession, tom: User, applet_with_flow: AppletFull +) -> AppletFull: + srv = AppletService(session, tom.id) + data = applet_with_flow.dict() + activity_flow = data["activity_flows"][0] + for i in range(len(activity_flow["items"])): + activity_flow["items"][i]["activity_key"] = data["activities"][0]["key"] + data["activity_flows"] = [activity_flow] + update_data = AppletUpdate(**data) + updated_applet = await srv.update(applet_with_flow.id, update_data) + return updated_applet diff --git a/src/apps/answers/tests/test_answers.py b/src/apps/answers/tests/test_answers.py index 293cb050991..f8c13ce026c 100644 --- a/src/apps/answers/tests/test_answers.py +++ b/src/apps/answers/tests/test_answers.py @@ -1922,7 +1922,7 @@ async def test_activity_turned_into_assessment_not_included_in_list( assert response.json()["result"][0]["id"] == str(applet__activity_turned_into_assessment.activities[1].id) async def test_deleted_activity_without_answers_not_included_in_list( - self, client: TestClient, tom: User, applet__deleted_activity_without_answers + self, client: TestClient, tom: User, applet__deleted_activity_without_answers: AppletFull ): client.login(tom) response = await client.get( @@ -1934,3 +1934,15 @@ async def test_deleted_activity_without_answers_not_included_in_list( assert response.status_code == http.HTTPStatus.OK assert response.json()["count"] == 1 assert response.json()["result"][0]["id"] == str(applet__deleted_activity_without_answers.activities[0].id) + + async def test_deleted_flow_not_included_in_submission_list( + self, client: TestClient, tom: User, applet__deleted_flow_without_answers: AppletFull + ): + client.login(tom) + url = self.summary_activity_flows_url.format(applet_id=applet__deleted_flow_without_answers.id) + response = await client.get(url) + assert response.status_code == 200 + payload = response.json() + assert applet__deleted_flow_without_answers.activity_flows[0].id + assert payload["count"] == 1 + assert payload["result"][0]["id"] == str(applet__deleted_flow_without_answers.activity_flows[0].id) From c8cd28a0e310000ce692790f68afc80cf63cc209 Mon Sep 17 00:00:00 2001 From: ivan koryshkin Date: Wed, 5 Jun 2024 18:27:30 +0400 Subject: [PATCH 3/3] wip(summary-activities) Rename method --- src/apps/activity_flows/crud/flow_history.py | 2 +- src/apps/answers/service.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/apps/activity_flows/crud/flow_history.py b/src/apps/activity_flows/crud/flow_history.py index f9c128601e7..6661ce44d5a 100644 --- a/src/apps/activity_flows/crud/flow_history.py +++ b/src/apps/activity_flows/crud/flow_history.py @@ -113,7 +113,7 @@ async def get_versions_data(self, flow_id: uuid.UUID) -> list[Version]: return parse_obj_as(list[Version], data) - async def get_by_applet_version(self, applet_id_version: str) -> list[ActivityFlowHistoriesSchema]: + async def get_by_applet_id_version(self, applet_id_version: str) -> list[ActivityFlowHistoriesSchema]: query: Query = select(ActivityFlowHistoriesSchema) query = query.where(ActivityFlowHistoriesSchema.applet_id == applet_id_version) query = query.join(AppletHistorySchema, AppletHistorySchema.id_version == ActivityFlowHistoriesSchema.applet_id) diff --git a/src/apps/answers/service.py b/src/apps/answers/service.py index 8901a4d7083..ec678bee2d2 100644 --- a/src/apps/answers/service.py +++ b/src/apps/answers/service.py @@ -1087,7 +1087,7 @@ async def get_summary_activity_flows( submitted_activity_flows[flow_id] = max(submit_date, date) if date else submit_date submitted_activity_flows[version_id] = submit_date - flow_histories = await flow_crud.get_by_applet_version(current_applet_version) + flow_histories = await flow_crud.get_by_applet_id_version(current_applet_version) flow_histories_curr = [flow_h.id for flow_h in flow_histories] results = [] for flow_history in activity_flow_histories: