You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
4.3 KiB
140 lines
4.3 KiB
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)
|