From 9fa010e7ae6c2eac61f8a1c55158644e0571353f Mon Sep 17 00:00:00 2001 From: Yamila Moreno Date: Tue, 7 Nov 2023 09:14:17 +0100 Subject: [PATCH] feat(notifications): u#3985 notify when a story has changed workflow (and status) --- .../stories/stories/notifications/__init__.py | 25 +++++++++++++++++++ .../stories/stories/notifications/content.py | 11 ++++++++ .../stories/stories/services/__init__.py | 9 ++++++- .../taiga/stories/stories/test_services.py | 5 +++- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/python/apps/taiga/src/taiga/stories/stories/notifications/__init__.py b/python/apps/taiga/src/taiga/stories/stories/notifications/__init__.py index 173656281..ea9a72741 100644 --- a/python/apps/taiga/src/taiga/stories/stories/notifications/__init__.py +++ b/python/apps/taiga/src/taiga/stories/stories/notifications/__init__.py @@ -10,10 +10,12 @@ from taiga.stories.stories.notifications.content import ( StoryDeleteNotificationContent, StoryStatusChangeNotificationContent, + StoryWorkflowChangeNotificationContent, ) from taiga.users.models import User STORIES_STATUS_CHANGE = "stories.status_change" +STORIES_WORKFLOW_CHANGE = "stories.workflow_change" STORIES_DELETE = "stories.delete" @@ -39,6 +41,29 @@ async def notify_when_story_status_change(story: Story, status: str, emitted_by: ) +async def notify_when_story_workflow_change(story: Story, workflow: str, status: str, emitted_by: User) -> None: + """ + Emit notification when a story workflow changes + """ + notified_users = {u async for u in story.assignees.all()} + if story.created_by: + notified_users.add(story.created_by) + notified_users.discard(emitted_by) + + await notifications_services.notify_users( + type=STORIES_WORKFLOW_CHANGE, + emitted_by=emitted_by, + notified_users=notified_users, + content=StoryWorkflowChangeNotificationContent( + project=story.project, + story=story, + changed_by=emitted_by, + workflow=workflow, + status=status, + ), + ) + + async def notify_when_story_is_deleted(story: Story, emitted_by: User) -> None: """ Emit notification when a story is deleted diff --git a/python/apps/taiga/src/taiga/stories/stories/notifications/content.py b/python/apps/taiga/src/taiga/stories/stories/notifications/content.py index e1358f976..89dbaae2f 100644 --- a/python/apps/taiga/src/taiga/stories/stories/notifications/content.py +++ b/python/apps/taiga/src/taiga/stories/stories/notifications/content.py @@ -28,3 +28,14 @@ class StoryStatusChangeNotificationContent(BaseModel): class Config: orm_mode = True + + +class StoryWorkflowChangeNotificationContent(BaseModel): + project: ProjectLinkNestedSerializer + story: StoryNestedSerializer + changed_by: UserNestedSerializer + status: str + workflow: str + + class Config: + orm_mode = True diff --git a/python/apps/taiga/src/taiga/stories/stories/services/__init__.py b/python/apps/taiga/src/taiga/stories/stories/services/__init__.py index b696030e4..7b7e9e73f 100644 --- a/python/apps/taiga/src/taiga/stories/stories/services/__init__.py +++ b/python/apps/taiga/src/taiga/stories/stories/services/__init__.py @@ -197,7 +197,14 @@ async def update_story( ) # Emit notifications - if "status" in update_values: + if "workflow" in update_values: + await stories_notifications.notify_when_story_workflow_change( + story=story, + workflow=update_values["workflow"].name, + status=update_values["status"].name, + emitted_by=updated_by, + ) + elif "status" in update_values: await stories_notifications.notify_when_story_status_change( story=story, status=update_values["status"].name, diff --git a/python/apps/taiga/tests/unit/taiga/stories/stories/test_services.py b/python/apps/taiga/tests/unit/taiga/stories/stories/test_services.py index b7b3666a0..1020b1b2f 100644 --- a/python/apps/taiga/tests/unit/taiga/stories/stories/test_services.py +++ b/python/apps/taiga/tests/unit/taiga/stories/stories/test_services.py @@ -250,6 +250,7 @@ async def test_update_story_ok(): updates_attrs=[*values], ) fake_notifications.notify_when_story_status_change.assert_not_awaited() + fake_notifications.notify_when_story_workflow_change.assert_not_awaited() assert updated_story == detailed_story @@ -324,7 +325,8 @@ async def test_update_story_workflow_ok(): updates_attrs=[*values], ) - fake_notifications.notify_when_story_status_change.assert_awaited_once() + fake_notifications.notify_when_story_status_change.assert_not_awaited() + fake_notifications.notify_when_story_workflow_change.assert_awaited_once() async def test_update_story_error_wrong_version(): @@ -365,6 +367,7 @@ async def test_update_story_error_wrong_version(): fake_get_story_detail.assert_not_awaited() fake_stories_events.emit_event_when_story_is_updated.assert_not_awaited() fake_notifications.notify_when_story_status_change.assert_not_awaited() + fake_notifications.notify_when_story_workflow_change.assert_not_awaited() #######################################################