from django.conf import settings from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ class SupportRoom(models.Model): class StatusChoices(models.TextChoices): OPEN = 'open', _('Open') PENDING = 'pending', _('Pending Support Reply') ANSWERED = 'answered', _('Answered') CLOSED = 'closed', _('Closed') user = models.OneToOneField( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='support_room', verbose_name=_('User'), ) status = models.CharField( max_length=20, choices=StatusChoices.choices, default=StatusChoices.OPEN, db_index=True, verbose_name=_('Status'), ) assigned_to = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='assigned_support_rooms', verbose_name=_('Assigned Specialist'), ) unread_by_admin = models.PositiveIntegerField( default=0, verbose_name=_('Unread by Admin'), ) unread_by_user = models.PositiveIntegerField( default=0, verbose_name=_('Unread by User'), ) last_message_at = models.DateTimeField( null=True, blank=True, db_index=True, verbose_name=_('Last Message At'), ) created_at = models.DateTimeField( auto_now_add=True, verbose_name=_('Created At'), ) updated_at = models.DateTimeField( auto_now=True, verbose_name=_('Updated At'), ) class Meta: verbose_name = _('Support Room') verbose_name_plural = _('Support Rooms') ordering = ('-last_message_at', '-created_at') def __str__(self): user_label = self.user.email or self.user.fullname or f"Guest #{self.user_id}" return f"Support Room #{self.pk} - {user_label}" class SupportMessage(models.Model): class SenderType(models.TextChoices): USER = 'user', _('User') SUPPORT = 'support', _('Support Specialist') room = models.ForeignKey( SupportRoom, on_delete=models.CASCADE, related_name='messages', verbose_name=_('Support Room'), ) sender_type = models.CharField( max_length=16, choices=SenderType.choices, default=SenderType.USER, db_index=True, verbose_name=_('Sender Type'), ) sender = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='sent_support_messages', verbose_name=_('Sender User'), ) content = models.TextField( verbose_name=_('Message Content'), ) is_read = models.BooleanField( default=False, db_index=True, verbose_name=_('Is Read'), ) created_at = models.DateTimeField( auto_now_add=True, db_index=True, verbose_name=_('Created At'), ) class Meta: verbose_name = _('Support Message') verbose_name_plural = _('Support Messages') ordering = ('id',) def __str__(self): return f"[{self.sender_type}] Room #{self.room_id}: {self.content[:40]}" def save(self, *args, **kwargs): is_new = self.pk is None super().save(*args, **kwargs) if is_new and self.room_id: now = self.created_at or timezone.now() if self.sender_type == self.SenderType.USER: SupportRoom.objects.filter(pk=self.room_id).update( last_message_at=now, status=SupportRoom.StatusChoices.PENDING, unread_by_admin=models.F('unread_by_admin') + 1, updated_at=now, ) elif self.sender_type == self.SenderType.SUPPORT: SupportRoom.objects.filter(pk=self.room_id).update( last_message_at=now, status=SupportRoom.StatusChoices.ANSWERED, unread_by_user=models.F('unread_by_user') + 1, unread_by_admin=0, updated_at=now, ) SupportMessage.objects.filter( room_id=self.room_id, sender_type=self.SenderType.USER, is_read=False, ).update(is_read=True)