Corp/backend/communications/services/message_deletion.py

47 lines
1.6 KiB
Python

from __future__ import annotations
from django.db import transaction
from django.db.models import F, Q
from django.utils import timezone
from communications.models import ChatReadState, Message
def soft_delete_message(
message: Message,
*,
deleted_by,
replacement_content: str | None = None,
) -> bool:
"""Soft-delete a message and remove it from cached unread counters."""
with transaction.atomic():
locked_message = Message.objects.select_for_update().get(pk=message.pk)
if locked_message.is_deleted:
return False
unread_states = ChatReadState.objects.filter(
chat_id=locked_message.chat_id,
unread_count__gt=0,
).exclude(user_id=locked_message.author_id)
unread_states = unread_states.filter(
Q(last_read_message_id__isnull=True)
| Q(last_read_message_id__lt=locked_message.id)
)
unread_states.update(unread_count=F("unread_count") - 1)
locked_message.is_deleted = True
locked_message.deleted_at = timezone.now()
locked_message.deleted_by = deleted_by
update_fields = ["is_deleted", "deleted_at", "deleted_by"]
if replacement_content is not None:
locked_message.content = replacement_content
update_fields.append("content")
locked_message.save(update_fields=update_fields)
message.is_deleted = locked_message.is_deleted
message.deleted_at = locked_message.deleted_at
message.deleted_by = locked_message.deleted_by
if replacement_content is not None:
message.content = replacement_content
return True