75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
from __future__ import annotations
|
|
|
|
from django.core.exceptions import ValidationError
|
|
from django.db.models import (
|
|
CharField,
|
|
DateTimeField,
|
|
EmailField,
|
|
ForeignKey,
|
|
Index,
|
|
JSONField,
|
|
TextChoices,
|
|
TextField,
|
|
SET_NULL,
|
|
CASCADE,
|
|
)
|
|
from django.utils import timezone
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from core.abstract import NiceModel
|
|
from vibes_auth.models import User
|
|
|
|
|
|
class ThreadStatus(TextChoices):
|
|
OPEN = "open", _("Open")
|
|
CLOSED = "closed", _("Closed")
|
|
|
|
|
|
class SenderType(TextChoices):
|
|
USER = "user", _("User")
|
|
STAFF = "staff", _("Staff")
|
|
SYSTEM = "system", _("System")
|
|
|
|
|
|
class ChatThread(NiceModel):
|
|
user = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="chat_threads")
|
|
email = EmailField(blank=True, default="", help_text=_("For anonymous threads"))
|
|
assigned_to = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="assigned_chat_threads")
|
|
status = CharField(max_length=16, choices=ThreadStatus.choices, default=ThreadStatus.OPEN)
|
|
last_message_at = DateTimeField(default=timezone.now)
|
|
attributes = JSONField(default=dict, blank=True)
|
|
|
|
class Meta:
|
|
indexes = [
|
|
Index(fields=["status", "modified"], name="chatthread_status_mod_idx"),
|
|
Index(fields=["assigned_to", "status"], name="chatthread_assigned_status_idx"),
|
|
Index(fields=["user"], name="chatthread_user_idx"),
|
|
Index(fields=["email"], name="chatthread_email_idx"),
|
|
]
|
|
ordering = ("-modified",)
|
|
verbose_name = _("Chat thread")
|
|
verbose_name_plural = _("Chat threads")
|
|
|
|
def clean(self) -> None:
|
|
super().clean()
|
|
if not self.user and not self.email:
|
|
raise ValidationError({"email": _("Provide user or email for anonymous thread.")})
|
|
if self.assigned_to and not self.assigned_to.is_staff:
|
|
raise ValidationError({"assigned_to": _("Assignee must be a staff user.")})
|
|
|
|
|
|
class ChatMessage(NiceModel):
|
|
thread = ForeignKey(ChatThread, on_delete=CASCADE, related_name="messages")
|
|
sender_type = CharField(max_length=16, choices=SenderType.choices)
|
|
sender_user = ForeignKey(User, null=True, blank=True, on_delete=SET_NULL, related_name="chat_messages")
|
|
text = TextField()
|
|
sent_at = DateTimeField(default=timezone.now)
|
|
attributes = JSONField(default=dict, blank=True)
|
|
|
|
class Meta:
|
|
indexes = [
|
|
Index(fields=["thread", "sent_at"], name="chatmessage_thread_sent_idx"),
|
|
]
|
|
ordering = ("sent_at", "uuid")
|
|
verbose_name = _("Chat message")
|
|
verbose_name_plural = _("Chat messages")
|