Files
smoothschedule/smoothschedule/tickets/signals.py

118 lines
5.4 KiB
Python

from django.db.models.signals import post_save
from django.dispatch import receiver
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
from django.contrib.contenttypes.models import ContentType
from .models import Ticket, TicketComment
from notifications.models import Notification # Assuming notifications app is installed
@receiver(post_save, sender=Ticket)
def ticket_notification_handler(sender, instance, created, **kwargs):
channel_layer = get_channel_layer()
# Logic for Ticket assignment and status change
if not created: # Only on update
# Get old instance (this is tricky with post_save, usually requires pre_save)
# For simplicity, we'll assume the instance passed is the new state,
# and compare against previous state if we had it.
# For now, let's just trigger on any save after creation, and focus on assignee.
# Notify assignee if changed
if instance.assignee:
# Check if assignee actually changed (requires pre_save or a custom field for old value)
# For this iteration, let's just notify the assignee on any update to the ticket they are assigned to
# Or if it's a new assignment.
# Create Notification object for the assignee
Notification.objects.create(
recipient=instance.assignee,
actor=instance.creator, # The one who created the ticket (can be updated later)
verb=f"Ticket #{instance.id} '{instance.subject}' was updated.",
action_object=instance,
target=instance,
data={'ticket_id': instance.id, 'subject': instance.subject, 'status': instance.status}
)
# Send WebSocket message to assignee's personal channel
async_to_sync(channel_layer.group_send)(
f"user_{instance.assignee.id}",
{
"type": "notification_message",
"message": {
"type": "ticket_update",
"ticket_id": instance.id,
"subject": instance.subject,
"status": instance.status,
"assignee_id": str(instance.assignee.id),
"message": f"Ticket #{instance.id} '{instance.subject}' updated. Status: {instance.status}"
}
}
)
# General notification for tenant/platform admins (if needed)
# This might be too broad, usually target specific groups/users
pass
@receiver(post_save, sender=TicketComment)
def comment_notification_handler(sender, instance, created, **kwargs):
if created:
channel_layer = get_channel_layer()
ticket = instance.ticket
# Notify creator of the ticket (if not the commenter)
if ticket.creator and ticket.creator != instance.author:
# Create Notification object for the ticket creator
Notification.objects.create(
recipient=ticket.creator,
actor=instance.author,
verb=f"New comment on your ticket #{ticket.id} '{ticket.subject}'.",
action_object=instance,
target=ticket,
data={'ticket_id': ticket.id, 'subject': ticket.subject, 'comment_id': instance.id}
)
# Send WebSocket message to creator's personal channel
async_to_sync(channel_layer.group_send)(
f"user_{ticket.creator.id}",
{
"type": "notification_message",
"message": {
"type": "new_comment",
"ticket_id": ticket.id,
"subject": ticket.subject,
"comment_id": instance.id,
"author_name": instance.author.full_name,
"message": f"New comment on your ticket #{ticket.id} from {instance.author.full_name}."
}
}
)
# Notify assignee of the ticket (if not the commenter and not the creator)
if ticket.assignee and ticket.assignee != instance.author and ticket.assignee != ticket.creator:
# Create Notification object for the ticket assignee
Notification.objects.create(
recipient=ticket.assignee,
actor=instance.author,
verb=f"New comment on ticket #{ticket.id} '{ticket.subject}' you are assigned to.",
action_object=instance,
target=ticket,
data={'ticket_id': ticket.id, 'subject': ticket.subject, 'comment_id': instance.id}
)
# Send WebSocket message to assignee's personal channel
async_to_sync(channel_layer.group_send)(
f"user_{ticket.assignee.id}",
{
"type": "notification_message",
"message": {
"type": "new_comment",
"ticket_id": ticket.id,
"subject": ticket.subject,
"comment_id": instance.id,
"author_name": instance.author.full_name,
"message": f"New comment on ticket #{ticket.id} you are assigned to from {instance.author.full_name}."
}
}
)