UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: корректный flow уведомлений Tasker

This commit is contained in:
DCCONSTRUCTIONS
2026-05-12 15:11:17 +03:00
parent 6737138ab7
commit fc59481703
17 changed files with 717 additions and 164 deletions
@@ -62,7 +62,7 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
notifications = (
Notification.objects.filter(workspace__slug=slug, receiver_id=request.user.id)
.filter(entity_name="issue")
.filter(Q(entity_name="issue") | Q(sender__startswith="in_app:nodedc:"))
.annotate(is_inbox_issue=Exists(intake_issue))
.annotate(is_intake_issue=Exists(intake_issue))
.annotate(
@@ -22,7 +22,7 @@ from plane.app.serializers import (
from plane.app.permissions import WorkspaceUserPermission
from plane.db.models import IssueAssignee, Project, ProjectMember, ProjectUserProperty, WorkspaceMember
from plane.db.models import IssueAssignee, Notification, Project, ProjectMember, ProjectUserProperty, WorkspaceMember
from plane.bgtasks.project_add_user_email_task import project_add_user_email
from plane.utils.host import base_host
from plane.app.permissions.base import allow_permission, ROLE
@@ -145,6 +145,36 @@ class ProjectMemberViewSet(BaseViewSet):
project_members = ProjectMember.objects.filter(
project_id=project_id,
member_id__in=[member.get("member_id") for member in members],
).select_related("member", "project", "workspace")
Notification.objects.bulk_create(
[
Notification(
workspace=project_member.workspace,
project=project_member.project,
sender="in_app:nodedc:project_member_added",
triggered_by=request.user,
receiver=project_member.member,
entity_identifier=project_member.project_id,
entity_name="project_member_added",
title=f"Вам открыли доступ к проекту {project_member.project.name}",
message=f"Вы добавлены в проект {project_member.project.name} workspace {project_member.workspace.name}.",
message_stripped=(
f"Вы добавлены в проект {project_member.project.name} workspace {project_member.workspace.name}."
),
data={
"notification_type": "project_member_added",
"target_url": f"/{slug}/projects/{project_id}/issues",
"workspace_slug": slug,
"workspace_name": project_member.workspace.name,
"project_id": str(project_member.project_id),
"project_name": project_member.project.name,
"role": project_member.role,
},
)
for project_member in project_members
if project_member.member_id != request.user.id
],
batch_size=10,
)
# Send emails to notify the users
[
@@ -37,7 +37,7 @@ from plane.app.serializers import (
from plane.app.views.base import BaseAPIView
from plane.bgtasks.event_tracking_task import track_event
from plane.bgtasks.workspace_invitation_task import workspace_invitation
from plane.db.models import User, Workspace, WorkspaceMember, WorkspaceMemberInvite
from plane.db.models import Notification, User, Workspace, WorkspaceMember, WorkspaceMemberInvite
from plane.utils.cache import invalidate_cache, invalidate_cache_directly
from plane.utils.host import base_host
from plane.utils.analytics_events import USER_JOINED_WORKSPACE, USER_INVITED_TO_WORKSPACE
@@ -314,6 +314,31 @@ class WorkspaceJoinEndpoint(BaseAPIView):
"joined_at": str(timezone.now()),
},
)
if workspace_invite.created_by_id and workspace_invite.created_by_id != user.id:
Notification.objects.create(
workspace=workspace_invite.workspace,
sender="in_app:nodedc:workspace_invite_accepted",
triggered_by=user,
receiver_id=workspace_invite.created_by_id,
entity_identifier=workspace_invite.workspace_id,
entity_name="workspace_invite_accepted",
title=f"{user.display_name or user.email} принял приглашение",
message=(
f"{user.display_name or user.email} присоединился к workspace "
f"{workspace_invite.workspace.name}."
),
message_stripped=(
f"{user.display_name or user.email} присоединился к workspace "
f"{workspace_invite.workspace.name}."
),
data={
"notification_type": "workspace_invite_accepted",
"target_url": f"/{workspace_invite.workspace.slug}/settings/members",
"workspace_slug": workspace_invite.workspace.slug,
"workspace_name": workspace_invite.workspace.name,
"invitee_email": user.email,
},
)
# Delete the invitation
workspace_invite.delete()
@@ -358,6 +383,7 @@ class UserWorkspaceInvitationsViewSet(BaseViewSet):
).order_by("-created_at")
# If the user is already a member of workspace and was deactivated then activate the user
accepted_notifications = []
for invitation in workspace_invitations:
workspace_member = WorkspaceMember.objects.filter(
workspace_id=invitation.workspace_id, member=request.user
@@ -394,6 +420,33 @@ class UserWorkspaceInvitationsViewSet(BaseViewSet):
"joined_at": str(timezone.now()),
},
)
if invitation.created_by_id and invitation.created_by_id != request.user.id:
accepted_notifications.append(
Notification(
workspace=invitation.workspace,
sender="in_app:nodedc:workspace_invite_accepted",
triggered_by=request.user,
receiver_id=invitation.created_by_id,
entity_identifier=invitation.workspace_id,
entity_name="workspace_invite_accepted",
title=f"{request.user.display_name or request.user.email} принял приглашение",
message=(
f"{request.user.display_name or request.user.email} присоединился к workspace "
f"{invitation.workspace.name}."
),
message_stripped=(
f"{request.user.display_name or request.user.email} присоединился к workspace "
f"{invitation.workspace.name}."
),
data={
"notification_type": "workspace_invite_accepted",
"target_url": f"/{invitation.workspace.slug}/settings/members",
"workspace_slug": invitation.workspace.slug,
"workspace_name": invitation.workspace.name,
"invitee_email": request.user.email,
},
)
)
# Bulk create the user for all the workspaces
WorkspaceMember.objects.bulk_create(
@@ -408,6 +461,7 @@ class UserWorkspaceInvitationsViewSet(BaseViewSet):
],
ignore_conflicts=True,
)
Notification.objects.bulk_create(accepted_notifications, batch_size=10)
# Delete joined workspace invites
workspace_invitations.delete()