Corp/backend/tasks/signals.py

95 lines
2.8 KiB
Python

import logging
from django.core.files.base import ContentFile
from django.db import transaction
from django.db.models.signals import post_delete, post_save, pre_save
from django.dispatch import receiver
from common.image_utils import compress_avatar
from .models import Task, TaskActivity, TaskAttachment, TaskBoard
logger = logging.getLogger(__name__)
def _delete_file_after_commit(field_file):
if not field_file or not field_file.name:
return
storage = field_file.storage
name = field_file.name
transaction.on_commit(
lambda: storage.delete(name) if storage.exists(name) else None
)
@receiver(pre_save, sender=TaskBoard)
def compress_and_cleanup_task_board_avatar(sender, instance, **kwargs):
old_avatar = None
if instance.pk:
old_avatar = (
sender.objects.filter(pk=instance.pk)
.only("avatar")
.values_list("avatar", flat=True)
.first()
)
new_avatar = instance.avatar
if new_avatar and not getattr(new_avatar, "_committed", True):
try:
compressed = compress_avatar(new_avatar.read())
if compressed:
new_avatar.save(
new_avatar.name,
ContentFile(compressed),
save=False,
)
except Exception:
new_avatar.seek(0)
logger.exception(
"Task board avatar compression failed",
extra={
"event": "task.board.avatar.compression_failed",
"task_board_id": instance.pk,
},
)
new_avatar_name = new_avatar.name if new_avatar else None
if old_avatar and old_avatar != new_avatar_name:
storage = instance._meta.get_field("avatar").storage
transaction.on_commit(
lambda: storage.delete(old_avatar) if storage.exists(old_avatar) else None
)
@receiver(post_delete, sender=TaskBoard)
def delete_task_board_avatar(sender, instance, **kwargs):
_delete_file_after_commit(instance.avatar)
@receiver(post_save, sender=Task)
def ensure_task_core_participants(sender, instance, **kwargs):
participant_ids = [instance.created_by_id]
if instance.assignee_id:
participant_ids.append(instance.assignee_id)
instance.participants.add(*participant_ids)
@receiver(post_delete, sender=TaskAttachment)
def delete_task_attachment_file(sender, instance, **kwargs):
_delete_file_after_commit(instance.file)
@receiver(post_save, sender=TaskActivity)
def dispatch_task_automation_event(sender, instance, created, **kwargs):
if not created:
return
activity_id = instance.id
def dispatch():
from tasks.tasks import process_task_automation_event_task
process_task_automation_event_task.delay(activity_id)
transaction.on_commit(dispatch)