83 lines
2.7 KiB
Python
83 lines
2.7 KiB
Python
from dataclasses import dataclass
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.db import transaction
|
|
from django.db.models import Q
|
|
from django.utils import timezone
|
|
|
|
from notifications.cache import invalidate_unread_summary
|
|
from notifications.models import Notification
|
|
from notifications.realtime import send_notifications_read_all_event
|
|
from tasks.models import Task, TaskBoard
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class TaskBoardNotificationReadResult:
|
|
notification_ids: list[int]
|
|
count: int
|
|
|
|
|
|
class TaskBoardNotificationReadService:
|
|
"""Marks only notifications related to one task board as read."""
|
|
|
|
def mark_board_notifications_as_read(
|
|
self,
|
|
*,
|
|
user,
|
|
board: TaskBoard,
|
|
) -> TaskBoardNotificationReadResult:
|
|
queryset = self._get_unread_queryset(user_id=user.id, board=board)
|
|
notification_ids = list(queryset.values_list("id", flat=True))
|
|
if not notification_ids:
|
|
return TaskBoardNotificationReadResult([], 0)
|
|
|
|
count = Notification.objects.filter(id__in=notification_ids).update(
|
|
unread=False,
|
|
timestamp_read=timezone.now(),
|
|
)
|
|
invalidate_unread_summary(user.id)
|
|
|
|
def notify_after_commit():
|
|
invalidate_unread_summary(user.id)
|
|
send_notifications_read_all_event(user.id, notification_ids)
|
|
|
|
transaction.on_commit(notify_after_commit)
|
|
return TaskBoardNotificationReadResult(notification_ids, count)
|
|
|
|
def _get_unread_queryset(self, *, user_id: int, board: TaskBoard):
|
|
task_content_type = ContentType.objects.get_for_model(Task)
|
|
board_content_type = ContentType.objects.get_for_model(TaskBoard)
|
|
board_id = board.id
|
|
board_id_text = str(board_id)
|
|
task_ids = [
|
|
str(task_id) for task_id in board.tasks.values_list("id", flat=True)
|
|
]
|
|
|
|
board_filter = (
|
|
Q(data__board_id=board_id)
|
|
| Q(data__board_id=board_id_text)
|
|
| Q(
|
|
action_object_content_type=board_content_type,
|
|
action_object_object_id=board_id_text,
|
|
)
|
|
)
|
|
if task_ids:
|
|
board_filter |= Q(
|
|
target_content_type=task_content_type,
|
|
target_object_id__in=task_ids,
|
|
) | Q(
|
|
action_object_content_type=task_content_type,
|
|
action_object_object_id__in=task_ids,
|
|
)
|
|
|
|
return (
|
|
Notification.objects.filter(
|
|
recipient_id=user_id,
|
|
unread=True,
|
|
deleted=False,
|
|
verb__startswith="task_",
|
|
)
|
|
.filter(board_filter)
|
|
.distinct()
|
|
)
|